Question

I am parsing a very large XML file with XMLReader.

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

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

A while loop is used to display relevant data based on user input as well as building arrays with XML values.

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

// Relevant search results displayed here:
echo "Category: " . $category . ". ";
echo "Name: " . $name . ". ";
echo "Price: " . $price . ". ";


$nameArray[] = $name;

}
$reader->next('product');
}

The foreach loop below uses the array that is built in the while loop above. I need these values (displayed in this foreach loop below) to appear BEFORE the while loop above displays the relevant search results. With XMLReader, you can only execute one while loop for each time you parse the XML, and I don't want to parse it twice because of memory and overhead issues. What is the best way to do this?

foreach ($nameArray as $names) {
echo $names . " "; 
}
Was it helpful?

Solution

Well… there are not many options. The most effectiv straight-forward approach is to store category/name/price in array instead of outputting them directly:

<?php
$data = array();
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);

        $data[] = array($category, $name, $price);
        $nameArray[] = $name;
    }

    $reader->next('product');
}

foreach ($nameArray as $names) {
    echo $names . " "; 
}

foreach ($data as $datum) {
    // Relevant search results displayed here:
    echo "Category: " . $datum[0] . ". ";
    echo "Name: " . $datum[1] . ". ";
    echo "Price: " . $datum[2] . ". ";
}

In case that doesn't work memory-wise (you mentioned that XML file is really large) you should use db- or file-backed temporary storage

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