XMLReader::read

(PHP 5 >= 5.1.0, PHP 7)

XMLReader::readMove to next node in document

说明

public XMLReader::read ( void ) : bool

Moves cursor to the next node in the document.

返回值

成功时返回 TRUE, 或者在失败时返回 FALSE

参见

User Contributed Notes

peter at 3xe dot co dot uk 13-Oct-2016 12:08
Another approach to the 'also reads closing tags' gotcha:

<?php
$reader
= new XMLReader();
$reader->open('users.xml');

while (
$reader->read()) {
  if (
$reader->nodeType == XMLReader::END_ELEMENT) {
    continue;
//skips the rest of the code in this iteration
 
}
 
//do something with desired node type
 
if($reader->name == 'user') {
   
//...
 
}
}
?>
Anonymous 20-Mar-2015 09:49
> I would have liked to use the next() function instead, but as I needed to parse 2 different subtrees, I couldn't figure out how to find all the columns, reset the pointer, and then find all the rows.

I just use:

$reader->close();
$reader->open($url);

to reset the pointer.
ecziegler at gmail 29-Jan-2014 12:27
If like myself you have been turning the interwebz upside down looking for a solution for this issue:
PHP Warning:  XMLReader::read(): /tmp/xml_feed.xml:4183934: parser error : Input is not proper UTF-8, indicate encoding !

For some reason, this warning breaks the execution - is it a fatal error in disguise?

After days of frustration I found it!!!!
tidy -xml -o output.xml -utf8 -f error.log input.xml

You can invoque tidy using exec, It takes several seconds to convert a 250Mb feed, but it worthy the time.

In my case the issue was with latin1 charset, and for some reason I had to pass the xml through tidy 2 times - first time around creates new errors, second time it fixes everything.

I know invalid xml should be fixed by xml creators, but it works differently in the real world.
Nate 27-Jun-2011 10:49
It is interesting to note that this function will stop on closing tags as well.  I have an XML document similar to the following:

<root>
  <columns>
    <column>columnX</column>
    <column>columnY</column>
  </columns>
  <table>
    <row>
      <columnX>38</columnX>
      <columnY>50</columnY>
    </row>
    <row>
      <columnX>82</columnY>
      <columnY>28</columnY>
    </row>
    ...
  </table>
</root>

I need to parse the <columns> object to know what attributes to check for from each <row> node.  Therefore I was doing the following:

<?php
while ($xml->read()) {
  if (
$xml->name === 'column') {
  
//parse column node to into $columns array
 
}
  elseif (
$xml->name === 'row') {
   
//parse row node, using constructed $columns array
 
}
}
?>

This kind of worked in that I ended up with an array of all the data I wanted, but the array I constructed was twice as large as I expected and every other entry was empty.  Took me a while to debug, but finally figured out that checking <?php $xml->name === 'row' ?> matches both <row> and </row>, so the check should really be something more like:

<?php

if ($xml->name === 'row' && $xml->nodeType == XMLReader::ELEMENT) {
 
// parse row node
}

?>

I would have liked to use the next() function instead, but as I needed to parse 2 different subtrees, I couldn't figure out how to find all the columns, reset the pointer, and then find all the rows.
andy at siliconrockstar dot com 16-May-2011 01:01
A very simple way to avoid typing $reader->read() multiple times when you want to skip some nodes:

<?php
class smartXMLReader extends XMLReader {
    public function
readTimes($count) {
       
$i = 0;
        while(
$i < $count){
           
$this->read();
           
$i++;
        }
    }
}
?>

Using this smartXMLReader,

<?php
$reader
->readTimes(3);
?>

is equivalent to

<?php
$reader
->read();
$reader->read();
$reader->read();
?>

Makes getting around in your XML document a bit easier :)
jirka at kosek dot cz 08-Feb-2006 01:01
libxml2 contains much more useful method readString() that will read and return whole text content of element. You can call it after receiving start tag (XMLReader::ELEMENT). You can use this PHP code to emulate this method until PHP will directly call underlying libxml2 implementation.

<?php
class XMLReader2 extends XMLReader
{
  function
readString()
  {
       
$depth = 1;
       
$text = "";

        while (
$this->read() && $depth != 0)
        {
            if (
in_array($this->nodeType, array(XMLReader::TEXT, XMLReader::CDATA, XMLReader::WHITESPACE, XMLReader::SIGNIFICANT_WHITESPACE)))
               
$text .= $this->value;
            if (
$this->nodeType == XMLReader::ELEMENT) $depth++;
            if (
$this->nodeType == XMLReader::END_ELEMENT) $depth--;
        }
        return
$text;
    }
}
?>

Just use XMLReader2 instead of XMLReader.