Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SimpleXML how to get line number of a node?

I'm using this in SimpleXML and PHP:

foreach ($xml->children() as $node) {
    echo $node->attributes('namespace')->id;
}

That prints the id attribute of all nodes (using a namespace).

But now I want to know the line number that $node is located in the XML file.

I need the line number, because I'm analyzing the XML file, and returning to the user information of possible issues to resolve them. So I need to say something like: "Here you have an error at line X". I'm sure that the XML file would be in a standard format that will have enough line breaks for this to be useful.

like image 300
ismaestro Avatar asked Dec 19 '22 05:12

ismaestro


1 Answers

It is possible with DOM. DOMNode provides the function getLineNo().

DOM

$xml = <<<'XML'
<foo>
  <bar/>
</foo>
XML;

$dom = new DOMDocument();
$dom->loadXml($xml);
$xpath = new DOMXpath($dom);

var_dump(
  $xpath->evaluate('//bar[1]')->item(0)->getLineNo()
);

Output:

int(2)

SimpleXML

SimpleXML is based on DOM, so you can convert SimpleXMLElement objects to DOMElement objects.

$element = new SimpleXMLElement($xml);
$node = dom_import_simplexml($element->bar);
var_dump($node->getLineNo());

And yes, most of the time if you have a problem with SimpleXML, the answer is to use DOM.

XMLReader

XMLReader has the line numbers internally, but here is no direct method to access them. Again you will have to convert it into a DOMNode. It works because both use libxml2. This will read the node and all its descendants into memory, so be careful with it.

$reader = new XMLReader();
$reader->open('data://text/xml;base64,'.base64_encode($xml));

while ($reader->read()) {
  if ($reader->nodeType == XMLReader::ELEMENT && $reader->name== 'bar') {
    var_dump($reader->expand()->getLineNo());
  }
}
like image 110
ThW Avatar answered Dec 24 '22 03:12

ThW