Re: Sequential access of XML nodes.
| From: | Richard Quadling | Date: | Wed, 28 Sep 2011 11:10:25 +0000 |
| Subject: | Re: Sequential access of XML nodes. | ||
| References: | 1 2 3 | Groups: | php.general |
| Request: | Send a blank email to php-general+get-315039@lists.php.net to get a copy of this message | ||
On 27 September 2011 03:38, Ross McKay <rosko@zeta.org.au> wrote:
> On Mon, 26 Sep 2011 14:17:43 -0400, Adam Richardson wrote:
>
>>I believe the XMLReader allows you to pull node by node, and it's really
>>easy to work with:
>>http://www.php.net/manual/en/intro.xmlreader.php
>>
>>In terms of dealing with various forms of compression, I believe you con use
>>the compression streams to handle this:
>>http://stackoverflow.com/questions/1190906/php-open-gzipped-xml
>>http://us3.php.net/manual/en/wrappers.compression.php
>
> +1 here. XMLReader is easy and fast, and will do the job you want albeit
> without the nice foreach(...) loop Richard spec's. You just loop over
> reading the XML and checking the node type, watching the state of your
> stream to see how to handle each iteration.
>
> e.g. (assuming $xml is an open XMLReader, $db is PDO in example)
>
> $text = '';
> $haveRecord = FALSE;
> $records = 0;
>
> // prepare insert statement
> $sql = '
> insert into Product (ID, Product, ...)
> values (:ID, :Product, ...)
> ';
> $cmd = $db->prepare($sql);
>
> // set list of allowable fields and their parameter type
> $fields = array(
> 'ID' => PDO::PARAM_INT,
> 'Product' => PDO::PARAM_STR,
> ...
> );
>
> while ($xml->read()) {
> switch ($xml->nodeType) {
> case XMLReader::ELEMENT:
> if ($xml->name === 'Product') {
> // start of Product element,
> // reset command parameters to empty
> foreach ($fields as $name => $type) {
> $cmd->bindValue(":$name", NULL, PDO::PARAM_NULL);
> }
> $haveRecord = TRUE;
> }
> $text = '';
> break;
>
> case XMLReader::END_ELEMENT:
> if ($xml->name === 'Product') {
> // end of Product element, save record
> if ($haveRecord) {
> $result = $cmd->execute();
> $records++;
> }
> $haveRecord = FALSE;
> }
> elseif ($haveRecord) {
> // still inside a Product element,
> // record field value and move on
> $name = $xml->name;
> if (array_key_exists($name, $fields)) {
> $cmd->bindValue(":$name", $text, $fields[$name]);
> }
> }
> $text = '';
> break;
>
> case XMLReader::TEXT:
> case XMLReader::CDATA:
> // record value (or part value) of text or cdata node
> $text .= $xml->value;
> break;
>
> default:
> break;
> }
> }
>
> return $records;
Thanks for all of that.
It seems that the SimpleXMLIterator is perfect for me.
I need to see if the documents I'm needing to process have multiple
namespaces. If they have do, then I'm not exactly sure what to do at
this stage.
Richard.
--
Richard Quadling
Twitter : EE : Zend : PHPDoc
@RQuadling : e-e.com/M_248814.html : bit.ly/9O8vFY : bit.ly/lFnVea