15

Say my XML looks like this:

<record>
  <row name="title">this item</row>
  <row name="url">this url</row>
</record>

Now I'm doing something like this:

$xml = new DOMDocument();
$xml->load('xmlfile.xml');

echo $xml->getElementByTagName('row')->item(0)->attributes->getNamedItem('title')->nodeValue;

But this just gives me:

NOTICE: Trying to get property of non-object id

Does anybody know how to get the node value where the "name" attribute has value "title"?

Frits
  • 151
  • 1
  • 1
  • 4
  • with XPath: `/record/row[@name='title']`. – Gordon Jul 26 '11 at 09:25
  • Like Michael answered in answer #3. This lookes like the right way to go. But I can't get it to work. – Frits Jul 26 '11 at 10:13
  • see [my answer here](http://stackoverflow.com/questions/4225227/php-xpath-on-xml/4225256#4225256) for a full example with DOM and SimpleXML. Just adapt it to your XML. There is plenty of additional examples on StackOverflow showing DOM usage. – Gordon Jul 26 '11 at 10:23
  • Thanks Gordon, but like I said so in others answers I don't want to use a foreach loop due to memory usage of it. – Frits Jul 26 '11 at 10:37
  • if memory is an issue you shouldnt be using DOM in the first place. It will use about ten times the size of the source document because it has to expand the xml into a tree. Try XML Reader then. The foreach is definitely not an issue at all. – Gordon Jul 26 '11 at 10:46
  • Ok, Gordon I thank you for the solution! Because I'm now a happy man with a succesfull working script with XMLReader. And it's fast too! To Bad I can't select your comment as a solution. – Frits Jul 27 '11 at 14:01

3 Answers3

15

Try:

$xml = new DOMDocument();
$xml->loadXml('
<record>
  <row name="title">this item</row>
  <row name="url">this url</row>
</record>
');

$xpath = new DomXpath($xml);

// traverse all results
foreach ($xpath->query('//row[@name="title"]') as $rowNode) {
    echo $rowNode->nodeValue; // will be 'this item'
}

// Or access the first result directly
$rowNode = $xpath->query('//row[@name="title"][1]')->item(0);
if ($rowNode instanceof DomElement) {
    echo $rowNode->nodeValue;
}
B. Chakib
  • 3
  • 2
Yoshi
  • 51,516
  • 13
  • 81
  • 100
  • 2
    I don't want to use a foreach. It takes far to much memory to go through the whole XML for this one item. – Frits Jul 26 '11 at 10:11
  • 4
    @Frits The `foreach` is just an example of how to use the result of `$xpath->query` (wich will be a [DOMNodeList](http://php.net/manual/class.domnodelist.php)). Also I added some code, to show how you can access the first result directly. – Yoshi Jul 26 '11 at 10:19
  • problem is solved with XMLReader as mentioned by Gordon as a comment on my post. Thank you for helping though. – Frits Jul 27 '11 at 14:02
  • @saravanabawa don't use [`loadXml`](https://php.net/manual/domdocument.loadxml.php) to load html, use [`loadHtml`](https://php.net/manual/domdocument.loadhtml.php) instead. – Yoshi Jun 11 '15 at 08:59
11
foreach ($xml->getElementsByTagName('row') as $element)
{
if ($element->getAttribute('name') == "title")
{
 echo $element->nodeValue;
}
}
Liam Bailey
  • 5,691
  • 3
  • 30
  • 44
  • 1
    I don't want to use a foreach. It takes far to much memory to go through the whole XML for this one item. – Frits Jul 26 '11 at 10:11
  • the html I'm working with might not be valid xml, so I appreciate that this solution doesn't rely on treating the html as xml. – alexanderbird Dec 02 '15 at 07:18
3
$xpath = new DOMXPath( $xml );
$val = $xpath->query( '//row[@name="title"]' )->item(0)->nodeValue;
hashchange
  • 5,971
  • 1
  • 40
  • 40
  • This leaves me with the same php notice. Notice: Trying to get property of non-object in – Frits Jul 26 '11 at 10:09
  • I tried with your code, worked for me. You'll get the notice if the XPath doesn't match - then item(0) is not a DOMElement and you can't read the nodeValue, hence the message. Do you use namespaces in your XML, or is it the exact same content as you posted it? – hashchange Jul 26 '11 at 10:42
  • problem is solved with XMLReader as mentioned by Gordon as a comment on my post. Thank you for helping though. – Frits Jul 27 '11 at 14:02