1

I have an XML like the one below, I am trying to do an xpath query and parse it with simplexml. The XML is a CURL response and is stored in a $response variable. I need to look the Code attribute inside the <Item> and select the parent <Product> to parse it.

$response:

<Items>
 <Product>
  <Item Code="123">
  </Item>
  <Price>170
  </Price>
 </Product>
 <Product>
  <Item Code="456">
  </Item>
  <Price>150
  </Price>
 </Product>
</Items>

This is what I am doing:

$xml = simplexml_import_dom($response); 

function loadNode($code){
    global $xml;
    $scode = $xml->xpath('//Item[contains(@Code,"' . $code . '")]/..');
    echo $scode->Items->Product->Price;
}

loadNode("123");

This is the Notice I get:

Notice: Trying to get property of non-object

Passerby
  • 9,715
  • 2
  • 33
  • 50
enriqg9
  • 1,455
  • 1
  • 21
  • 40
  • [`SimpleXMLElement::xpath()`](http://www.php.net/manual/en/simplexmlelement.xpath.php) returns an array, not a SimpleXMLElement object. – Passerby Nov 01 '13 at 03:26
  • The xpath looks not too bad, you might want to use `sprintf()` with `%d` probably to [prevent xpath injection](http://hakre.wordpress.com/2013/07/11/mitigating-xpath-injection-attacks-in-php/): `list($scode) = $xml->xpath(sprintf('//Item[contains(@Code, "%d")]/..', $code);` and you're probably interested in: [How to get useful error messages in PHP?](http://stackoverflow.com/q/845021/367456). – hakre Nov 01 '13 at 06:35

1 Answers1

1

A couple of observations:

  • The xpath() method returns an array of SimpleXMLElement objects, not a single SimpleXMLElement. (Yes, even though there can only be a single parent of an element, you still have to get it as the first member of the array ([0]).
  • $scode->Items->Product->Price should be changed to just $scode->Price.

These modifications to your PHP code:

<?php
$response = <<<XML
<Items>
  <Product>
    <Item Code="123">
    </Item>
    <Price>170
    </Price>
  </Product>
  <Product>
    <Item Code="456">
    </Item>
    <Price>150
    </Price>
  </Product>
</Items>
XML;

$xml = simplexml_load_string($response);

function loadNode($code) {
  global $xml;
  $scode = $xml->xpath('//Item[contains(@Code,' . $code . ')]/..')[0];
  echo $scode->Price;
}

loadNode("123");
?>

When run will yield this output:

170

as expected.

kjhughes
  • 106,133
  • 27
  • 181
  • 240