0

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 . " "; 
}
Dean Olsen
  • 131
  • 4
  • 13

1 Answers1

0

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

JimiDini
  • 2,039
  • 12
  • 19
  • Thanks! There will only be 10 to 20 search results per page (containing category, name and a few more variables along with a thumbnail) so memory probably wont be an issue. I've been playing around with buffering (IE ob_start(); ob_end_flush();) and haven't been able to get that to work. Would you consider buffering an option? – Dean Olsen Apr 19 '14 at 21:29
  • buffering would work too, but buffering would require a bit more memory (so I didn't suggest it). and I would do it a bit differently: 1). `ob_start();` 2). `$contents = ob_get_flush();` 3). `foreach () {…}` 4) `echo $contents;` – JimiDini Apr 20 '14 at 11:39