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

标签 php xml xmlreader xmlwriter data-manipulation

我有一个非常非常大的 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/

相关文章:

java - 无法使用 Log4j2 在控制台中记录消息,但它们已记录在文件中

android - java.lang.Class java.lang.Object.getClass()' 在空对象引用上

mysql - 如何将XML数据导入mysql表

php xmlReader 与 xmlparser

c# - XmlReaders 是否返回 XML 声明?

.net - 从 XmlReader 读取 XElement

php - 激活 MySQL 扩展时,Apache/PHP 无法在 WinXP 上启动

javascript - 您如何使用 php 强制打开 Jquery Mobile 弹出窗口?

php - 使用 css、外部内容将 div 保持在所需位置

php - 将数据保存到数据透视表中 - 多对多关系 - Laravel