Question

With XMLReader, I am trying to parse a very large XML only ONCE, but use multiple while loops from the one parse of the XML file, as coded below. Is that possible? It would seem to save on overhead and memory consumption by only parsing the large file once.

$reader = new XMLReader;
$reader->open('products.xml');
$dom = new DOMDocument;
$xpath = new DOMXpath($dom);

while ($reader->read() && $reader->name !== 'product') {
continue;
}

This while loop executes correctly and fills the array with values

while ($reader->name === 'product') {
$node = $dom->importNode($reader->expand(), TRUE);

if ($xpath->evaluate('number(price)', $node) > $price_submitted) {
$name = $xpath->evaluate('string(name)', $node);
$nameArray[] = $name;
}
$reader->next('product');
}

This while loop does NOT execute correctly and nothing is echoed, and this needs to be done in a separate while loop from the one above for display purposes

while ($reader->name === 'product') {
$node = $dom->importNode($reader->expand(), TRUE);

if ($xpath->evaluate('number(price)', $node) > $price_submitted) {

$category = $xpath->evaluate('string(@category)', $node);
$name = $xpath->evaluate('string(name)', $node);
$price = $xpath->evaluate('number(price)', $node);

echo "Category: " . $category . ". ";
echo "Name: " . $name . ". ";
echo "Price: " . $price . ". ";
echo "<br>";
}
$reader->next('product');
}

With simpleXML, you can use multiple foreach loops from a single parsing of the file, which I am trying to do with XMLReader above.

foreach($XMLproducts->product as $Product) {
if ($Product->price > $price_submitted) {
$nameArray[] = $name;
}}

foreach($XMLproducts->product as $Product) {
if ($Product->price > $price_submitted) {
echo $Product->name . " " . $Product->price
}}
Was it helpful?

Solution

As far as I understand the XmlReader API it works forwards only and once you have parsed a node you can't go back. Thus if you have one while loop which consumes all the product elements a second loop will not be able to find any more of those elements as the reader is positioned after the last product element when the second loops starts. SimpleXML is different, it builds a tree I think so you can go back and read out nodes several times if needed. If you want to use the XmlReader API then you have to write one loop reading out the product elements and buffer the data you want to output later or in a different place.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top