jjzjj

PHP XMLReader 读取、编辑 Node 、写入 XMLWriter

coder 2024-04-05 原文

我有一个非常非常大的 XML 文件(数百万条记录)。由于速度和内存限制,我计划使用 XMLReader/XMLWriter

我需要读取文件,获取一条记录,更改其属性,最后再次保存 XML。

为了测试,我创建了一个 XML 文件并使用这些行将一些记录写入其中:

$doc = new XMLWriter();  
$doc->openURI($xmlFile);  
$doc->startDocument('1.0','UTF-8');  
$doc->setIndent(4);   
$doc->startElement('DBOS'); 
for($r=0;$r<10; $r++){
    $doc->startElement('ITEMS');
    for($i=0;$i<5; $i++){
        $doc->startElement('ITEM');  
        $doc->writeAttribute('id', $r.'-'.$i);
        $doc->endElement();
    }
    $doc->endElement();
}
$doc->endElement();  
$doc->endDocument();   
$doc->flush();

我用这个再次阅读了它:

$reader = new XMLReader();
if (!$reader->open($xmlFile)){
    die("Failed to open 'data.xml'");
}
while($reader->read()){
    if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == 'ITEMS') {
        $node = $reader->expand();
        $items = $node->childNodes;
        foreach ($items as $ik => $itm ){
            print $itm->textContent.'<br/>';
            // how to change the ID Attribute of a Node (DomNode) and save changes to the original XML File 
        }
        break;
    }
}
$reader->close();

我的问题:如何更改 DomNodeid 属性并将更改保存到原始 XML 文件使用 XMLWriter 又是?

最佳答案

How to change the id attribute of a DomNode and save changes to the original XML File using XMLWriter again?

这样不行。如果你同时使用 XMLReaderXMLWriter同一个文件进行操作,文件将被写入者截断,读取者将吐出错误并停止工作。

但是,您可以对不同 文件进行操作。

因此,您可以做的是使用 XMLReader 读取文档,并在对其进行操作时使用 XMLWriter 根据您的内容写入另一个文档阅读并偶尔修改。完成后,您可以将新写入的文件重命名为旧文件名。

例子

对于 XML 文档(例如,XMLReaderXMLWriter 对非常大的文档来说很自然地有意义)像这样模仿您的问题:

<DBOS>
    <ITEMS>
        <ITEM>item #1</ITEM>
        <ITEM>item #2</ITEM>
        <ITEM>item #3</ITEM>
    </ITEMS>
    <ITEMS>
        <ITEM>item #4</ITEM>
        <ITEM>item #5</ITEM>
    </ITEMS>
</DBOS>

一个工作代码示例是:

<?php
/*
 * This file is part of the XMLReaderIterator package.
 *
 * Copyright (C) 2012, 2014 hakre <http://hakre.wordpress.com>
 *
 * Example: Write XML with XMLWriter while reading from XMLReader with XMLWriterIteration
 */

require('xmlreader-iterators.php'); // require XMLReaderIterator library

$xmlInputFile  = 'data/dobs-items.xml';
$xmlOutputFile = 'php://output';

$reader = new XMLReader();
$reader->open($xmlInputFile);

$writer = new XMLWriter();
$writer->openUri($xmlOutputFile);

$iterator = new XMLWritingIteration($writer, $reader);

$writer->startDocument();

$itemsCount = 0;
$itemCount  = 0;
foreach ($iterator as $node) {
    $isElement = $node->nodeType === XMLReader::ELEMENT;


    if ($isElement && $node->name === 'ITEMS') {
        // increase counter for <ITEMS> elements and reset <ITEM> counter
        $itemsCount++;
        $itemCount = 0;
    }

    if ($isElement && $node->name === 'ITEM') {
        // increase <ITEM> counter and insert "id" attribute
        $itemCount++;
        $writer->startElement($node->name);
        $writer->writeAttribute('id', $itemsCount . "-" . $itemCount);
        if ($node->isEmptyElement) {
            $writer->endElement();
        }
    } else {
        // handle everything else
        $iterator->write();
    }
}

$writer->endDocument();

然后输出是(作为标准输出的示例,可以使用任何有效的 PHP 文件名):

<?xml version="1.0"?>
<DBOS>
    <ITEMS>
        <ITEM id="1-1">item #1</ITEM>
        <ITEM id="1-2">item #2</ITEM>
        <ITEM id="1-3">item #3</ITEM>
    </ITEMS>
    <ITEMS>
        <ITEM id="2-1">item #4</ITEM>
        <ITEM id="2-2">item #5</ITEM>
    </ITEMS>
</DBOS>

如本例所示,id 属性是根据不同计数器变量的编号添加的。

由于 $iterator->write()XMLWritingIteration 让这一切变得简单,因为它处理所有其他节点和案例。

示例和代码是 the XMLReaderIterator package 的一部分。还有另一个例子是基于 XMLReader 创建一个 DOMDocument,它是 an answer to "How to distinguish between empty element and null-size string in DOMDocument?" 的一部分。

关于PHP XMLReader 读取、编辑 Node 、写入 XMLWriter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21065150/

有关PHP XMLReader 读取、编辑 Node 、写入 XMLWriter的更多相关文章

  1. ruby-on-rails - Rails 编辑表单不显示嵌套项 - 2

    我得到了一个包含嵌套链接的表单。编辑时链接字段为空的问题。这是我的表格:Editingkategori{:action=>'update',:id=>@konkurrancer.id})do|f|%>'Trackingurl',:style=>'width:500;'%>'Editkonkurrence'%>|我的konkurrencer模型:has_one:link我的链接模型:classLink我的konkurrancer编辑操作:defedit@konkurrancer=Konkurrancer.find(params[:id])@konkurrancer.link_attrib

  2. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  3. Ruby 写入和读取对象到文件 - 2

    好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信

  4. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

  5. python - 如何读取 MIDI 文件、更改其乐器并将其写回? - 2

    我想解析一个已经存在的.mid文件,改变它的乐器,例如从“acousticgrandpiano”到“violin”,然后将它保存回去或作为另一个.mid文件。根据我在文档中看到的内容,该乐器通过program_change或patch_change指令进行了更改,但我找不到任何在已经存在的MIDI文件中执行此操作的库.他们似乎都只支持从头开始创建的MIDI文件。 最佳答案 MIDIpackage会为您完成此操作,但具体方法取决于midi文件的原始内容。一个MIDI文件由一个或多个音轨组成,每个音轨是十六个channel中任何一个上的

  6. STM32读取串口传感器数据(颗粒物传感器,主动上传) - 2

    文章目录1.开发板选择*用到的资源2.串口通信(个人理解)3.代码分析(注释比较详细)1.主函数2.串口1配置3.串口2配置以及中断函数4.注意问题5.源码链接1.开发板选择我用的是STM32F103RCT6的板子,不过代码大概在F103系列的板子上都可以运行,我试过在野火103的霸道板上也可以,主要看一下串口对应的引脚一不一样就行了,不一样的就更改一下。*用到的资源keil5软件这里用到了两个串口资源,采集数据一个,串口通信一个,板子对应引脚如下:串口1,TX:PA9,RX:PA10串口2,TX:PA2,RX:PA32.串口通信(个人理解)我就从串口采集传感器数据这个过程说一下我自己的理解,

  7. ruby - Ruby 是否使用 $stdout 来写入 puts 和 return 的输出? - 2

    我想知道Ruby用来在命令行打印这些东西的输出流:irb(main):001:0>a="test"=>"test"irb(main):002:0>putsatest=>nilirb(main):003:0>a=>"test"$stdout是否用于irb(main):002:0>和irb(main):003:0>?而且,在这两次调用之间,$stdout的值是否有任何变化?另外,有人能告诉我打印/写入这些内容的Ruby源代码吗? 最佳答案 是的。而且很容易向自己测试/证明。在命令行试试这个:ruby-e'puts"foo"'>test.

  8. ruby - 是否可以在不实际发送或读取数据的情况下查明 ruby​​ 套接字是否处于 ESTABLISHED 或 CLOSE_WAIT 状态? - 2

    s=Socket.new(Socket::AF_INET,Socket::SOCK_STREAM,0)s.connect(Socket.pack_sockaddr_in('port','hostname'))ssl=OpenSSL::SSL::SSLSocket.new(s,sslcert)ssl.connect从这里开始,如果ssl连接和底层套接字仍然是ESTABLISHED,或者它是否在默认值7200之后进入CLOSE_WAIT,我想检查一个线程几秒钟甚至更糟的是在实际上不需要.write()或.read()的情况下关闭。是用select()、IO.select()还是其他方法完成

  9. ruby - 如何从 ARGF 读取 csv - 2

    在Ruby1.9中,我如何从ARGF中读取CSV?我尝试了以下方法,但没有打印任何内容:require'csv'CSV(ARGF).readdo|row|prowendhttp://www.ruby-doc.org/core-1.9.3/ARGF.htmlhttp://ruby-doc.org/stdlib-1.9.2/libdoc/csv/rdoc/CSV.html 最佳答案 如果你想偷懒你可以试试:CSV.new(ARGF.file).eachdo|row|...end来源:http://www.ruby-doc.org/std

  10. Ruby:写入 stdin 并从 stdout 读取? - 2

    我正在编写一个ruby​​程序,它应该执行另一个程序,通过stdin向它传递值,从它的stdout读取响应,然后打印响应。这是我目前所拥有的。#!/usr/bin/envrubyrequire'open3'stdin,stdout,stderr=Open3.popen3('./MyProgram')stdin.puts"helloworld!"output=stdout.readerrors=stderr.readstdin.closestdout.closestderr.closeputs"Output:"puts"-------"putsoutputputs"\nErrors:"p

随机推荐