Sha*_*sri 74 php xml parsing xmlreader simplexml
我有以下XML文件,文件相当大,我无法让simplexml打开并读取文件所以我正在尝试XMLReader没有成功的PHP
<?xml version="1.0" encoding="ISO-8859-1"?>
<products>
<last_updated>2009-11-30 13:52:40</last_updated>
<product>
<element_1>foo</element_1>
<element_2>foo</element_2>
<element_3>foo</element_3>
<element_4>foo</element_4>
</product>
<product>
<element_1>bar</element_1>
<element_2>bar</element_2>
<element_3>bar</element_3>
<element_4>bar</element_4>
</product>
</products>
Run Code Online (Sandbox Code Playgroud)
遗憾的是,我没有为PHP找到一个很好的教程,我很想知道如何将每个元素内容存储在数据库中.
Jos*_*vis 212
这一切都取决于工作单元的大小,但我想你正试图<product/>连续对待每个节点.
为此,最简单的方法是使用XMLReader到达每个节点,然后使用SimpleXML访问它们.这样,您可以保持较低的内存使用率,因为您一次只处理一个节点,并且仍然可以利用SimpleXML的易用性.例如:
$z = new XMLReader;
$z->open('data.xml');
$doc = new DOMDocument;
// move to the first <product /> node
while ($z->read() && $z->name !== 'product');
// now that we're at the right depth, hop to the next <product/> until the end of the tree
while ($z->name === 'product')
{
// either one should work
//$node = new SimpleXMLElement($z->readOuterXML());
$node = simplexml_import_dom($doc->importNode($z->expand(), true));
// now you can use $node without going insane about parsing
var_dump($node->element_1);
// go to next <product />
$z->next('product');
}
Run Code Online (Sandbox Code Playgroud)
快速概述不同方法的优缺点:
仅限XMLReader
优点:速度快,占用内存少
缺点:编写和调试过于困难,需要大量用户态代码才能执行任何有用的操作.Userland代码很慢并且容易出错.此外,它还为您提供了更多维护代码
XMLReader + SimpleXML
优点:不使用太多内存(只处理一个节点所需的内存),顾名思义,SimpleXML非常易于使用.
缺点:为每个节点创建SimpleXMLElement对象的速度不是很快.你真的必须对它进行基准测试,以了解它是否适合你.但是,即使是适度的机器也能够每秒处理一千个节点.
XMLReader + DOM
优点:使用与SimpleXML一样多的内存,而XMLReader :: expand()比创建新的SimpleXMLElement更快.我希望它可以使用,simplexml_import_dom()但在这种情况下似乎不起作用
缺点:DOM很烦人.它位于XMLReader和SimpleXML之间.并不像XMLReader那样复杂和笨拙,但距离使用SimpleXML还有几年的时间.
我的建议:用SimpleXML编写一个原型,看看它是否适合你.如果性能至关重要,请尝试DOM.尽可能远离XMLReader.请记住,您编写的代码越多,引入错误或引入性能回归的可能性就越高.
对于使用属性格式化的xml ...
data.xml中:
<building_data>
<building address="some address" lat="28.902914" lng="-71.007235" />
<building address="some address" lat="48.892342" lng="-75.0423423" />
<building address="some address" lat="58.929753" lng="-79.1236987" />
</building_data>
Run Code Online (Sandbox Code Playgroud)
php代码:
$reader = new XMLReader();
if (!$reader->open("data.xml")) {
die("Failed to open 'data.xml'");
}
while($reader->read()) {
if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == 'building') {
$address = $reader->getAttribute('address');
$latitude = $reader->getAttribute('lat');
$longitude = $reader->getAttribute('lng');
}
$reader->close();
Run Code Online (Sandbox Code Playgroud)
我的大部分XML解析生命都花在从卡车的XML(亚马逊MWS)中提取大量有用信息.因此,我的回答是假设您只需要特定信息,并且您知道它的位置.
我发现使用XMLReader的最简单方法是知道我想要哪些标签信息并使用它们.如果你知道XML的结构并且它有很多独特的标签,我发现使用第一种情况很容易.案例2和案例3只是为了向您展示如何为更复杂的标签做到这一点.这非常快; 我讨论了什么是PHP中最快的XML解析器的速度?
在进行基于标记的解析时要记住的最重要的事情就是使用if ($myXML->nodeType == XMLReader::ELEMENT) {...- 检查以确保我们只处理打开节点而不是空白或关闭节点或其他什么.
function parseMyXML ($xml) { //pass in an XML string
$myXML = new XMLReader();
$myXML->xml($xml);
while ($myXML->read()) { //start reading.
if ($myXML->nodeType == XMLReader::ELEMENT) { //only opening tags.
$tag = $myXML->name; //make $tag contain the name of the tag
switch ($tag) {
case 'Tag1': //this tag contains no child elements, only the content we need. And it's unique.
$variable = $myXML->readInnerXML(); //now variable contains the contents of tag1
break;
case 'Tag2': //this tag contains child elements, of which we only want one.
while($myXML->read()) { //so we tell it to keep reading
if ($myXML->nodeType == XMLReader::ELEMENT && $myXML->name === 'Amount') { // and when it finds the amount tag...
$variable2 = $myXML->readInnerXML(); //...put it in $variable2.
break;
}
}
break;
case 'Tag3': //tag3 also has children, which are not unique, but we need two of the children this time.
while($myXML->read()) {
if ($myXML->nodeType == XMLReader::ELEMENT && $myXML->name === 'Amount') {
$variable3 = $myXML->readInnerXML();
break;
} else if ($myXML->nodeType == XMLReader::ELEMENT && $myXML->name === 'Currency') {
$variable4 = $myXML->readInnerXML();
break;
}
}
break;
}
}
}
$myXML->close();
}
Run Code Online (Sandbox Code Playgroud)
被接受的答案给了我一个良好的开端,但是带来了比我想要的更多的类和更多的处理。所以这是我的解释:
$xml_reader = new XMLReader;
$xml_reader->open($feed_url);
// move the pointer to the first product
while ($xml_reader->read() && $xml_reader->name != 'product');
// loop through the products
while ($xml_reader->name == 'product')
{
// load the current xml element into simplexml and we’re off and running!
$xml = simplexml_load_string($xml_reader->readOuterXML());
// now you can use your simpleXML object ($xml).
echo $xml->element_1;
// move the pointer to the next product
$xml_reader->next('product');
}
// don’t forget to close the file
$xml_reader->close();
Run Code Online (Sandbox Code Playgroud)