0

I am attempting to parse an xml file with attributes, and keep getting an empty array. Here is a sample of the xml, which is parsed as a simplexml_load_string:

     <NumberOfOfferListings>
    <OfferListingCount condition="Any">61</OfferListingCount>
    <OfferListingCount condition="Used">45</OfferListingCount>
    <OfferListingCount condition="New">16</OfferListingCount>
  </NumberOfOfferListings>

Here is the php code that I am using

$priceComp_xml = amazonCompPrice_xml($asin);
$compPricing = $priceComp_xml->xpath('OfferListingCount[@condition="Any"]'); 

amazonCompPrice($asin) is the parsed xml file based on the ASIN value.

I need to extract just:

<OfferListingCount condition="Any">61</OfferListingCount>

I have looked at many examples on here to get to this point, and it looks like what I have is correct, just returns an empty array when I use either print_r($compPricing) or var_dump. How do I fix this to get the information that I need?? I can upload any more snippets of code that will help resolve this issue.

2
  • Unless the XML you quoted is the entire document, your XPath query is not quite right. It only looks for an <OffsetListingCount> which is a child (c.f, descendant) of whatever $priceComp_xml holds. The simplest change would be to use //OfferListingCount[@condition="Any"] Commented Aug 30, 2012 at 18:48
  • I am a little confused, should it look like this then:$compPricing = $priceComp_xml->xpath('//OfferListingCount[@condition="Any"]'); Commented Aug 30, 2012 at 18:52

1 Answer 1

1

There are (at least) two separate issues at play here.

The XPath

Your XPath, OfferListingCount[@condition="Any"], will only return matching <OfferListingCount> elements which are children of the element held in $priceComp_xml. It will not match descendant elements which are grand-children, or further down the tree.

So, it needs to be amended to match the <OfferListingCount> element(s). A quick fix usually to employ the shorthand // (short for /descendant-or-self::node()/), like //OfferListingCount[@condition="Any"].

Namespaces

Your question did not mention this, but some digging uncovered that the XML document probably has a default namespace applied to it. This can be recognised by looking at the document element for xmlns="…". When using XPath, this namespace needs to be registered and used when querying.

$priceComp_xml->registerXPathNamespace('products', 'http://mws.amazonservices.com/schema/Products/2011-10-01');
$compPricing = $priceComp_xml->xpath('//products:OfferListingCount[@condition="Any"]');

Finally, remember that SimpleXMLElement::xpath() returns an array, so your matching <offerListingCount> element will be available as $compPricing[0].

$count = (int) $compPricing[0];
Sign up to request clarification or add additional context in comments.

4 Comments

Do I need this whole line <Product xmlns="mws.amazonservices.com/schema/Products/2011-10-01" xmlns:ns2="mws.amazonservices.com/schema/Products/2011-10-01/default.xsd"> or just the part that you posted?
Just the part I posted, the code registers a products prefix for the namespace URI http://mws.amazonservices.com/schema/Products/2011-10-01. This prefix can then be used in the query.
Registering the namespace seems to have done the trick! Thank You very much for the help!
You're welcome. A huge number of people stumble over that particular issue.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.