views:

954

answers:

2

I have the following XML file, the file is rather large and i haven't been able to get simplexml to open and read the file so i'm trying XMLREADER with no success in 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>

I've unfortunately not found a good tutorial on this for PHP and would love to see how i can get each element content to store in a database.

Cheers!

A: 

XMLReader is well documented on PHP site. This is a XML Pull Parser, which means it's used to iterate through nodes (or DOM Nodes) of given XML document. For example, you could go through the entire document you gave like this:

<?php
$reader = new XMLReader();
if (!$reader->open("data.xml"))
{
    die("Failed to open 'data.xml'");
}
while($reader->read())
{
    $node = $reader->expand();
    // process $node...
}
$reader->close();
?>

It is then up to you to decide how to deal with the node returned by XMLReader::expand().

JP
how will you get it to move to the next node after it has finished processing one?
Shadi Almosri
Also regarding XMLReader being well documented on php.net i would disagree, it's one of the worst documented functions i've seen and i've used php.net for a long time and it was the first place i headed to to resolve this before asking here :)
Shadi Almosri
I'm not sure you understand the way XMLReader::read() goes from one node to another. The XMLReader class also uses libxml, a well known library that is also available for PHP if you want to take a look at it.
JP
+4  A: 

It all depends on how big the unit of work, but I guess you're trying to treat each <product/> nodes in succession.

For that, the simplest way would be to use XMLReader to get to each node, then use SimpleXML to access them. This way, you keep the memory usage low because you're treating one node at a time and you still leverage SimpleXML's ease of use. For instance:

$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');
}

Quick overview of pros and cons of different approaches:

XMLReader only

  • Pros: fast, uses little memory

  • Cons: excessively hard to write and debug, requires lots of userland code to do anything useful. Userland code is slow and prone to error. Plus, it leaves you with more lines of code to maintain

XMLReader + SimpleXML

  • Pros: doesn't use much memory (only the memory needed to process one node) and SimpleXML is, as the name implies, really easy to use.

  • Cons: creating a SimpleXMLElement object for each node is not very fast. You really have to benchmark it to understand whether it's a problem for you. Even a modest machine would be able to process a thousand nodes per second, though.

XMLReader + DOM

  • Pros: uses about as much memory as SimpleXML, and XMLReader::expand() is faster than creating a new SimpleXMLElement. I wish it was possible to use simplexml_import_dom() but it doesn't seem to work in that case

  • Cons: DOM is annoying to work with. It's halfway between XMLReader and SimpleXML. Not as complicated and awkward as XMLReader, but light years away from working with SimpleXML.

My advice: write a prototype with SimpleXML, see if it works for you. If performance is paramount, try DOM. Stay as far away from XMLReader as possible. Remember that the more code you write, the higher the possibility of you introducing bugs or introducing performance regressions.

Josh Davis
is there a way to do this purely with XMLReader or is there no advantage?
Shadi Almosri
You could do it entirely with XMLReader. The advantage is that it would be faster and use marginally less memory. The disadvantage is it would take considerably longer to write and be very much harder to debug.
Josh Davis