The Amount
element is in the namespace <http://webservices.amazon.com/AWSECommerceService/2011-08-01>
. But in your xpath query you put it in no namespace at all. So the example will return 0 elements:
$xml = simplexml_load_string($buffer);
$result = $xml->xpath('//Amount');
printf("Result (%d):\n", count($result));
foreach ($result as $node) {
echo $node->asXML(), "\n";
}
The output is rather short:
Result (0):
Instead you need to tell that you want the Amount
element in that specific namespace. You do that by registering a namespace-prefix and use it in your xpath query:
$xml->registerXPathNamespace("amazon", "http://webservices.amazon.com/AWSECommerceService/2011-08-01");
$result = $xml->xpath('//amazon:Amount');
printf("Result (%d):\n", count($result));
foreach ($result as $node) {
echo $node->asXML(), "\n";
}
Now the output is with all those elements:
Result (24):
<Amount>217</Amount>
<Amount>1</Amount>
<Amount>800</Amount>
<Amount>1</Amount>
<Amount>498</Amount>
...
Take care that if you've got more than one element-name to check for in your xpath query, that you need to tell the correct namespace for each of them. Example:
$result = $xml->xpath('/*/amazon:Items/amazon:Item//amazon:Amount');
You can find the example code also online here: https://eval.in/314347 (backup)- otherwise the examples from my answer minus the XML at a glance:
$xml = simplexml_load_string($buffer);
$result = $xml->xpath('//Amount');
printf("Result (%d):\n", count($result));
foreach ($result as $node) {
echo $node->asXML(), "\n";
}
$xml->registerXPathNamespace("amazon", "http://webservices.amazon.com/AWSECommerceService/2011-08-01");
$result = $xml->xpath('//amazon:Amount');
printf("Result (%d):\n", count($result));
foreach ($result as $node) {
echo $node->asXML(), "\n";
}
$result = $xml->xpath('/*/amazon:Items/amazon:Item//amazon:Amount');
printf("Result (%d):\n", count($result));
foreach ($result as $node) {
echo $node->asXML(), "\n";
}
Further Readings
If you don't want to register the namespace prefixes over and over again, you can extend from SimpleXMLElement and manage that registration list your own:
/**
* Class MyXml
*
* Example on how to register xpath namespace prefixes within the document
*/
class MyXml extends SimpleXMLElement
{
public function registerXPathNamespace($prefix, $ns)
{
$doc = dom_import_simplexml($this)->ownerDocument;
$doc->__sr = $doc;
$doc->__d[] = [$prefix, $ns];
}
public function xpath($path)
{
$doc = dom_import_simplexml($this)->ownerDocument;
if (isset($doc->__d)) {
foreach ($doc->__d as $v) {
parent::registerXPathNamespace($v[0], $v[1]);
}
}
return parent::xpath($path);
}
}
With this MyXml class you can load the document and then you would only need to register the namespace once:
$namespace = "http://webservices.amazon.com/AWSECommerceService/2011-08-01";
$xml = simplexml_load_file('so-29664051.xml', 'MyXMl');
$xml->registerXPathNamespace("amazon", $namespace);
$item = $xml->Items->Item[0];
$result = $item->xpath('.//amazon:Amount');
printf("Result (%d):\n", count($result));
foreach ($result as $node) {
echo $node->asXML(), "\n";
}