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.
XMLReader::read
(PHP 5 >= 5.1.0)
XMLReader::read — Déplace le curseur sur le prochain noeud du document
Description
bool XMLReader::read
( void
)
Déplace le curseur au prochain noeud texte du document.
Valeurs de retour
Cette fonction retourne TRUE en cas de
succès ou FALSE si une erreur survient.
Voir aussi
- XMLReader::moveToElement() - Positionne le curseur sur l'élément parent de l'attribut courant
- XMLReader::moveToAttribute() - Déplace un curseur à un attribut nommé
- XMLReader::next() - Déplace le curseur au prochain noeud en sautant tous les sous arbres
Nate ¶
1 year ago
jirka at kosek dot cz ¶
7 years ago
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.
andy at siliconrockstar dot com ¶
2 years ago
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 :)
Yannik ¶
3 years ago
If you have trouble parsing xml documents with text tags bigger than 10MB, this might help you:
<?php
$xmlreader = new XMLReader();
$xmlreader->open($uri, null, 1<<19);
?>
Since in libxml there is a constant
XML_PARSE_HUGE = 1<<19
which enables parsing xml documents with huge texts.
Please note that this option is not accessible using the setParserProperty method and that there is currently no constant to do the work, which will hopefully change soon:
http://bugs.php.net/bug.php?id=49660
caddozzone at gmail dot com ¶
2 years ago
This class XMLReader2 is dangerous: charge all XML in memory, it can cause an out of memory error. It's the same that SimpleXML does.
Please take care.
