Re: Sequential access of XML nodes.

From: 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

« previous php.general (#315039) next »