PHP XMLReader读取,编辑Node,编写XMLWriter [英] PHP XMLReader read , edit Node , write XMLWriter

查看:142
本文介绍了PHP XMLReader读取,编辑Node,编写XMLWriter的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个非常大的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(无法打开‘data.xml’);
}
while($ reader-> read()){
if($ reader-> nodeType == XMLReader :: ELEMENT&& $ reader-> name = ='ITEMS'){
$ node = $ reader-> expand();
$ items = $ node-> childNodes;
foreach($ item as $ ik => $ itm){
print $ itm-> textContent。’< br />’;
// //如何更改节点(DomNode)的ID属性并将更改保存到原始XML文件中
}
break;
}
}
$ reader-> close();

我的问题:如何更改 id DomNode 属性并再次使用XMLWriter 将更改保存到原始XML文件中?

解决方案


如何更改DomNode的id属性并再次使用XMLWriter将更改保存到原始XML文件中?


这种方式不起作用。如果您使用 XMLReader XMLWriter 同时对相同文件进行操作,该文件将被编写者截断,并且读者将吐出错误并停止工作。



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



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



示例



对于这样的XML文档(对于示例来说, XMLReader XMLWriter 对于大型文档自然是有意义的),就像这样,在您的问题之后进行了建模:

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

工作代码示例为:

 <?php 
/ *
*此文件是XMLReaderIterator包的一部分。
*
*版权所有(C)2012、2014 hakre< http://hakre.wordpress.com>
*
*示例:使用XMLWriter编写XML,同时使用XMLWriterIteration从XMLReader读取
* /

require(’xmlreader-iterators.php’); //需要XMLReaderIterator库

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

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

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

$ iterator =新的XMLWritingIteration($ writer,$ reader);

$ writer-> startDocument();

$ itemsCount = 0;
$ itemCount = 0;
foreach($迭代器作为$ node){
$ isElement = $ node-> nodeType === XMLReader :: ELEMENT;


if($ isElement&& $ node-> name ==='ITEMS'){
//增加< ITEMS>元素并重置< ITEM>计数器
$ itemsCount ++;
$ itemCount = 0;
}

if($ isElement&& $ node-> name ==='ITEM'){
//增加< ITEM>计数器并插入 id属性
$ itemCount ++;
$ writer-> startElement($ node-> name);
$ writer-> writeAttribute('id',$ itemsCount。-。$ itemCount);
if($ node-> isEmptyElement){
$ writer-> endElement();
}
} else {
//处理其他所有内容
$ iterator-> write();
}
}

$ writer-> endDocument();

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

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

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

XMLWritingIteration 使此操作变得容易,这要归功于 $ iterator-> write( )



该示例和代码是 XMLReaderIterator程序包。还有另一个示例是基于 XMLReader 创建 DOMDocument ,它是 如何在DOMDocument中区分空元素和空值字符串?的答案。


I have an XML file which is very very large (millions of records). Due to speed and memory constraints I plan to use XMLReader/XMLWriter.

I need to read the file, getting one record, change its attribute, and finally save XML again.

For testing I created an XML file and write some records into it using these lines:

$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();

I read it again using this:

$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();

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

解决方案

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

This does not work that way. If you use XMLReader and XMLWriter to operate on the same file simultaneously, the file will be truncated by the writer and the reader will spit errors and stop working.

However, you can operate on different files.

So what you can do is to use an XMLReader to read the document and while you operate on it use XMLWriter to write to another document based on what you've read and occasionally modified. After you're done, you can then rename the newly written file to the old filename.

Example

For an XML document (shortened for the example, XMLReader and XMLWriter make naturally sense with really huge documents) like this one modeled a bit after your question:

<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>

A working code-example is:

<?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();

The output then is (exemplary to standard output, any valid PHP file-name can be used):

<?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>

As this example shows, the id attributes are added based on the numbering by the different counter variables.

The XMLWritingIteration makes this easy as it deals with all other nodes and cases thanks to $iterator->write().

The example and code is part of the XMLReaderIterator package. There is also another example that is creating a DOMDocument based on XMLReader, it is part of an answer to "How to distinguish between empty element and null-size string in DOMDocument?".

这篇关于PHP XMLReader读取,编辑Node,编写XMLWriter的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆