This question already has answers here:
Reference - How do I handle Namespaces (Tags and Attributes with a Colon in their Name) in SimpleXML?
(2 answers)
Closed 2 years ago.
I m working with Amazon Marketplace Web Service (Amazon MWS) to fetch products.
I need to get the title of the first product :
For the ASIN, I can get it using :
$xml->ListMatchingProductsResult->Products->Product[0]->Identifiers->MarketplaceASIN->ASIN
but for the title, I dont konw how because of the "ns2".
here is the XML data :
<?xml version="1.0"?>
<ListMatchingProductsResponse xmlns="http://mws.amazonservices.com/schema/Products/2011-10-01">
<ListMatchingProductsResult>
<Products>
<Product>
<Identifiers>
<MarketplaceASIN>
<MarketplaceId>A2EUQ1WTGCTBG2</MarketplaceId>
<ASIN>B01MYV7W6A</ASIN>
</MarketplaceASIN>
</Identifiers>
<AttributeSets>
<ns2:ItemAttributes xmlns:ns2="http://mws.amazonservices.com/schema/Products/2011-10-01/default.xsd" xml:lang="en-CA">
<ns2:Binding>Automotive</ns2:Binding>
<ns2:Brand>Multiple Manufacturers</ns2:Brand>
<ns2:ItemDimensions>
<ns2:Weight Units="pounds">12</ns2:Weight>
</ns2:ItemDimensions>
<ns2:Label>Multiple Manufacturers</ns2:Label>
<ns2:Manufacturer>Multiple Manufacturers</ns2:Manufacturer>
<ns2:Model>AC1000149R</ns2:Model>
<ns2:PackageDimensions>
<ns2:Height Units="inches">18</ns2:Height>
<ns2:Length Units="inches">78</ns2:Length>
<ns2:Width Units="inches">38</ns2:Width>
<ns2:Weight Units="pounds">12</ns2:Weight>
</ns2:PackageDimensions>
<ns2:PackageQuantity>1</ns2:PackageQuantity>
<ns2:PartNumber>AC1000149R</ns2:PartNumber>
<ns2:ProductGroup>Automotive Parts and Accessories</ns2:ProductGroup>
<ns2:ProductTypeName>AUTO_ACCESSORY</ns2:ProductTypeName>
<ns2:Publisher>Multiple Manufacturers</ns2:Publisher>
<ns2:SmallImage>
<ns2:URL>https://m.media-amazon.com/images/I/31gfzCbfPRL._SL75_.jpg</ns2:URL>
<ns2:Height Units="pixels">75</ns2:Height>
<ns2:Width Units="pixels">75</ns2:Width>
</ns2:SmallImage>
<ns2:Studio>Multiple Manufacturers</ns2:Studio>
<ns2:Title>OE Replacement 2004-2006 Acura TL Bumper Cover (Partslink Number AC1000149)</ns2:Title>
</ns2:ItemAttributes>
</AttributeSets>
<Relationships/>
<SalesRankings/>
</Product>
</Products>
</ListMatchingProductsResult>
<ResponseMetadata>
<RequestId>83360543-e16c-4c0f-a4b5-5dcca89a3075</RequestId>
</ResponseMetadata>
</ListMatchingProductsResponse>
Thank you in advance.
Here is the solution I found :
$ItemAttributes = $xml->ListMatchingProductsResult->Products->Product[$i]->AttributeSets->ItemAttributes;
$ItemAttributes->registerXPathNamespace('ns2', 'http://mws.amazonservices.com/schema/Products/2011-10-01/default.xsd');
$titles = $ItemAttributes->xpath("//ns2:Title"); // <= this is array
Related
I'm trying to combine multiple XML files, using SimpleXML if possible. I'm just trying to append products, children, and child data from file 2 into file 1. I'm not trying to merge elements, just append file 2 to the bottom of file 1, and so on. (Though I guess this is technically merging merchandiser elements?) The files contain the same schema and will both look similar to the example below, only thing that will be changing is the actual text. This is just XML for two different products, I added a large space in between products so that it's easier to see where it ends.
<merchandiser xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="merchandiser.xsd">
<header>
<merchantId>35928</merchantId>
<merchantName>Sunspel Clothing</merchantName>
<createdOn>01/14/2016 02:03:31</createdOn>
</header>
<product product_id="14633" name="Cotton Socks" sku_number="1588/102">
<category>
<primary>Accessories</primary>
<secondary>Men's~~Socks</secondary>
</category>
<URL>
<product>
http://click.linksynergy.com/link?id=D*rqD2paIXY&offerid=191965.14633&type=15&murl=http%3A%2F%2Fwww.sunspel.com%2Fuk%2Fcotton-sock-black.html
</product>
<productImage>
http://www.sunspel.com/media/catalog/product/cache/1/image/9df78eab33525d08d6e5fb8d27136e95/1/5/1588-102-new.jpg
</productImage>
</URL>
<description>
<short>
Our new cotton socks are designed by Sunspel and crafted in an Italian factory steeped in years of experience, skill and heritage. They are made from the highest quality, extra-long staple Egyptian cotton yarn which, prior to knitting is combed, twisted and mercerised to enhance the comfort, shine and absorption of the fabric as well as its resistance to pilling and shrinking.
</short>
</description>
<discount currency="GBP">
<type>amount</type>
</discount>
<price currency="GBP">
<retail>15.00</retail>
</price>
<shipping>
<availability>in-stock</availability>
</shipping>
<pixel>
http://ad.linksynergy.com/fs-bin/show?id=D*rqD2paIXY&bids=191965.14633&type=15&subid=0
</pixel>
</product>
<product product_id="15115" name="Cotton Socks" sku_number="1589/236">
<category>
<primary>Accessories</primary>
<secondary>Men's~~Socks~~Men's</secondary>
</category>
<URL>
<product>
http://click.linksynergy.com/link?id=D*rqD2paIXY&offerid=191965.15115&type=15&murl=http%3A%2F%2Fwww.sunspel.com%2Fuk%2Fmens-cotton-socks-navy-stripes.html
</product>
<productImage>
http://www.sunspel.com/media/catalog/product/cache/1/image/9df78eab33525d08d6e5fb8d27136e95/1/5/1588-236-new.jpg
</productImage>
</URL>
<description>
<short>
Our new cotton socks are designed by Sunspel and crafted in an Italian factory steeped in years of experience, skill and heritage. They are made from the highest quality, extra-long staple Egyptian cotton yarn which, prior to knitting is combed, twisted and mercerised to enhance the comfort, shine and absorption of the fabric as well as its resistance to pilling and shrinking.
</short>
</description>
<discount currency="GBP">
<type>amount</type>
</discount>
<price currency="GBP">
<retail>17.00</retail>
</price>
<shipping>
<availability>in-stock</availability>
</shipping>
<pixel>
http://ad.linksynergy.com/fs-bin/show?id=D*rqD2paIXY&bids=191965.15115&type=15&subid=0
</pixel>
</product>
<product product_id="15116" name="Cotton Socks" sku_number="1589/711">
<category>
<primary>Accessories</primary>
<secondary>Men's~~Socks~~Men's</secondary>
</category>
<URL>
<product>
http://click.linksynergy.com/link?id=D*rqD2paIXY&offerid=191965.15116&type=15&murl=http%3A%2F%2Fwww.sunspel.com%2Fuk%2Fmens-cotton-socks-charcoal-melange-stripes.html
</product>
<productImage>
http://www.sunspel.com/media/catalog/product/cache/1/image/9df78eab33525d08d6e5fb8d27136e95/1/5/1588-711-new.jpg
</productImage>
</URL>
<description>
<short>
Our new cotton socks are designed by Sunspel and crafted in an Italian factory steeped in years of experience, skill and heritage. They are made from the highest quality, extra-long staple Egyptian cotton yarn which, prior to knitting is combed, twisted and mercerised to enhance the comfort, shine and absorption of the fabric as well as its resistance to pilling and shrinking.
</short>
</description>
<discount currency="GBP">
<type>amount</type>
</discount>
<price currency="GBP">
<retail>17.00</retail>
</price>
<shipping>
<availability>in-stock</availability>
</shipping>
<pixel>
http://ad.linksynergy.com/fs-bin/show?id=D*rqD2paIXY&bids=191965.15116&type=15&subid=0
</pixel>
</product>
With some foreach statements I'm able to append all product children and attributes, but this doesn't actually give me the child data.
$file1 = '35928_3210820_mp.xml';
$file2 = '39153_3210820_mp.xml';
$fileout = 'ukmerge.xml';
$xml1 = simplexml_load_file( $file1 );
$xml2 = simplexml_load_file( $file2 ); // loop through the product and add them and their attributes to xml1
$product = $xml2->product;
$prod = $xml2->merchandiser->header->product;
$category = $product->category;
$url = $product->URL;
$description = $product->description;
foreach( $xml2->children() as $child ) {
$new = $xml1->addChild( $child->getName() , htmlspecialchars($child) );
foreach( $child->attributes() as $key => $value ) {
$new->addAttribute( $key, $value );
}
} $fh = fopen( $fileout, 'w') or die ( "can't open file $fileout" );
fwrite( $fh, $xml1->asXML() );
fclose( $fh );
When I try to add on from there then everything gets messed up and nothing is in the correct place/order anymore. I'd also like to put this into a function since I'm going to be doing it often. Any help is greatly appreciate as I've been struggling with this for a few days now and have scowered over a few dozen stackoverflow and php.net threads.
One of the things that's confusing me is the <merchandiser> and <header> tags that every file starts with. Once the merchandiser tag ends it is the end of the document so I need to take only what's inside the merchandiser tag of file 2 and append it inside the merchandiser tag of file 1. The header tag just confuses me cause I'm not sure if it's gets in the way or not.
As preliminary note, your XML sample is malformed. Also it is not coherent with your code (i.e. there is not ->merchandiser->header->product ).
So, in this example I will use a different sample, like this one (file1.xml):
<root>
<product>
<name>Product 1</name>
</product>
<product>
<name>Product 2</name>
</product>
</root>
and this one (file2.xml):
<root>
<product>
<name>Product 3</name>
</product>
<product>
<name>Product 4</name>
</product>
</root>
You don't want to use DOMDocument->importNode() due “it kept throwing a lot of errors”.
You can use DOMDocument in conjunction with SimpleXML and dom_import_simplexml() function.
First of all, prepare destination XML: load the file with SimpleXML, create a DOMDocument using dom_import_simplexml() and set $parent variable to <root> element:
$dst = simplexml_load_file( 'file1.xml' );
$dst = dom_import_simplexml( $dst )->ownerDocument;
$parent = $dst->getElementsByTagName( 'root' )->item(0);
Then, load second file with SimpleXML:
$src = simplexml_load_file( 'file2.xml' );
Through a foreach() loop, import each <product> element from SimpleXML to DOMDocument and appent it as child of $parent node:
foreach( $src->product as $product )
{
$node = dom_import_simplexml( $product );
$node = $dst->importNode( $node, 1 );
$parent->appendChild( $node );
}
Now, your merged XML is ready. You can print it using $dst->saveXML().
I've not be able to product a correctly indented XML. BTW to do this, you can reload-it:
$final = new DOMDocument();
$final->loadXML( $dst->saveXML(), LIBXML_NOBLANKS );
$final->formatOutput = True;
echo $final->saveXML();
Final output:
<?xml version="1.0"?>
<root>
<product>
<name>Product 1</name>
</product>
<product>
<name>Product 2</name>
</product>
<product>
<name>Product 3</name>
</product>
<product>
<name>Product 4</name>
</product>
</root>
When searching through the XML that amazon gives me in return some products don't have an amount or package dimensions. The code the I have written so far to check that is this :
if($items->Products->Product->AttributeSets->children('ns2',TRUE)->ItemAttributes->ListPrice->Amount === null){
$amount = '0.00';
} elseif (isset($items->Products->Product->AttributeSets->children('ns2',TRUE)->ItemAttributes->ListPrice->Amount) === False){
$amount = $items->Products->Product->AttributeSets->children('ns2',TRUE)->ItemAttributes->ListPrice->Amount;
}else{
$amount = '0.00';
}
This code is the same for all of the problems. If I do not have these attributes set to null in the first if statement, then an error children() on null occurs. Which it would be if the attribute Amount was not found.
Example of Amount not being an attribute:
<GetMatchingProductForIdResult Id="082686074551" IdType="UPC" status="Success">
<Products>
<Product>
<Identifiers>
<MarketplaceASIN>
<MarketplaceId>ATVPDKIKX0DER</MarketplaceId>
<ASIN>B000UUZVI6</ASIN>
</MarketplaceASIN>
</Identifiers>
<AttributeSets>
<ns2:ItemAttributes xmlns:ns2="http://mws.amazonservices.com/schema/Products/2011-10-01/default.xsd" xml:lang="en-US">
<ns2:Binding>Toy</ns2:Binding>
<ns2:Brand>Rubie's</ns2:Brand>
<ns2:Color>White</ns2:Color>
<ns2:Department>unisex-child</ns2:Department>
<ns2:Feature>Size : For ages 4 and up</ns2:Feature>
<ns2:Label>Rubie's</ns2:Label>
<ns2:Manufacturer>Rubie's</ns2:Manufacturer>
<ns2:ProductGroup>Toy</ns2:ProductGroup>
<ns2:ProductTypeName>TOYS_AND_GAMES</ns2:ProductTypeName>
<ns2:Publisher>Rubie's</ns2:Publisher>
<ns2:SmallImage>
<ns2:URL>http://ecx.images-amazon.com/images/I/41u1YTVvESL._SL75_.jpg</ns2:URL>
<ns2:Height Units="pixels">75</ns2:Height>
<ns2:Width Units="pixels">67</ns2:Width>
</ns2:SmallImage>
<ns2:Studio>Rubie's</ns2:Studio>
<ns2:Title>Child Rose Print White Tights Stocking Costume</ns2:Title>
</ns2:ItemAttributes>
</AttributeSets>
<Relationships/>
<SalesRankings/>
</Product>
<Product>
</GetMatchingProductForIdResult>
With the Amount Attribute:
<GetMatchingProductForIdResult Id="082686075824" IdType="UPC" status="Success">
<Products>
<Product>
<Identifiers>
<MarketplaceASIN>
<MarketplaceId>ATVPDKIKX0DER</MarketplaceId>
<ASIN>B001R4FMEW</ASIN>
</MarketplaceASIN>
</Identifiers>
<AttributeSets>
<ns2:ItemAttributes xmlns:ns2="http://mws.amazonservices.com/schema/Products/2011-10-01/default.xsd" xml:lang="en-US">
<ns2:Binding>Toy</ns2:Binding>
<ns2:Brand>Rubie's</ns2:Brand>
<ns2:Color>Black</ns2:Color>
<ns2:Department>teen-girls</ns2:Department>
<ns2:Feature>Fun costumes for kids and adults</ns2:Feature>
<ns2:Feature>Whether it's for Halloween, a themed party, or even for giggles</ns2:Feature>
<ns2:Feature>Beautiful colors, hand-wash needed, excellent for dress up</ns2:Feature>
<ns2:ItemDimensions>
<ns2:Height Units="inches">8.00</ns2:Height>
<ns2:Length Units="inches">15.00</ns2:Length>
<ns2:Width Units="inches">8.00</ns2:Width>
</ns2:ItemDimensions>
<ns2:Label>Pro-Motion Distributing - Direct</ns2:Label>
<ns2:ListPrice>
<ns2:Amount>3.99</ns2:Amount>
<ns2:CurrencyCode>USD</ns2:CurrencyCode>
</ns2:ListPrice>
<ns2:Manufacturer>Pro-Motion Distributing - Direct</ns2:Manufacturer>
<ns2:ManufacturerMaximumAge Units="months">96.0</ns2:ManufacturerMaximumAge>
<ns2:ManufacturerMinimumAge Units="months">18.0</ns2:ManufacturerMinimumAge>
<ns2:Model>RUB7582ACC</ns2:Model>
<ns2:PackageDimensions>
<ns2:Height Units="inches">0.50</ns2:Height>
<ns2:Length Units="inches">8.00</ns2:Length>
<ns2:Width Units="inches">6.00</ns2:Width>
<ns2:Weight Units="pounds">0.20</ns2:Weight>
</ns2:PackageDimensions>
<ns2:PackageQuantity>1</ns2:PackageQuantity>
<ns2:PartNumber>RUB7582ACC</ns2:PartNumber>
<ns2:ProductGroup>Toy</ns2:ProductGroup>
<ns2:ProductTypeName>TOYS_AND_GAMES</ns2:ProductTypeName>
<ns2:Publisher>Pro-Motion Distributing - Direct</ns2:Publisher>
<ns2:Size>Teen</ns2:Size>
<ns2:SmallImage>
<ns2:URL>http://ecx.images-amazon.com/images/I/41A%2BY200WLL._SL75_.jpg</ns2:URL>
<ns2:Height Units="pixels">75</ns2:Height>
<ns2:Width Units="pixels">34</ns2:Width>
</ns2:SmallImage>
<ns2:Studio>Pro-Motion Distributing - Direct</ns2:Studio>
<ns2:Title>Rubie's Costume Co Skull Tights-White/Black Costume</ns2:Title>
<ns2:Warranty>30 day warranty against manufacturer defects</ns2:Warranty>
</ns2:ItemAttributes>
</AttributeSets>
<Relationships/>
<SalesRankings>
<SalesRank>
<ProductCategoryId>toy_display_on_website</ProductCategoryId>
<Rank>1121721</Rank>
</SalesRank>
<SalesRank>
<ProductCategoryId>251975011</ProductCategoryId>
<Rank>7203</Rank>
</SalesRank>
<SalesRank>
<ProductCategoryId>251940011</ProductCategoryId>
<Rank>10177</Rank>
</SalesRank>
</SalesRankings>
</Product>
</Products>
</GetMatchingProductForIdResult>
I don't understand what the problem could possibly be. I appreciate the help in advance.
It is failing because you are checking a node behind another node that does not exists.
In one example the node "ListPrice" is not present, but you are checking if "ListPrice->amount" == null so it launches an exception.
if($child->Products->Product->AttributeSets->children('ns2',TRUE)->ItemAttributes->ListPrice->Amount === null){
$amount = '0.00';
} elseif (isset($child->Products->Product->AttributeSets->children('ns2',TRUE)->ItemAttributes->ListPrice->Amount) === False){
$amount = $child->Products->Product->AttributeSets->children('ns2',TRUE)->ItemAttributes->ListPrice->Amount;
}else{
$amount = '0.00';
}
So if you want to avoid fails then try to check fist:
if isset( $child->.....->ListPrice) {
if isset( $child->....->ListPrice->amount ) {
// Here you are sure amount exists
$amount = $child->Products->Product->AttributeSets->children('ns2',TRUE)->ItemAttributes->ListPrice->Amount;
} else {
// Amount does not exists
$amount = 0.00;
}
} else {
// Amount does not exists
$amount = 0.00;
}
When i use this for loop :
for ($i = 0; $i < count($groupedArrays); $i++) {
$xmlFilePath = 'xml/' . $file_name . $i . '.xml';
$xml = simplexml_load_file($xmlFilePath);
echo $xmlFilePath;
foreach ($xml->children() as $items) {
//Pull UPC data
echo $items['Id'] . ',';
//Verify complete listing
if (isset($items->Products->Product->SalesRankings->SalesRank[0]->Rank) == false) {
//Pull ASIN data
echo $items->Products->Product->Identifiers->MarketplaceASIN->ASIN . ',';
//Pull pricing data
echo $items->Products->Product->AttributeSets->children('ns2', true)->ItemAttributes->ListPrice->Amount . ',';
continue;
}
//Pull sales rank data
echo $items->Products->Product->SalesRankings->SalesRank[0]->Rank . ',';
//Pull pricing data
echo $items->Products->Product->AttributeSets->children('ns2', true)->ItemAttributes->ListPrice->Amount . ',';
}
}
It does not return any values. I attempted echo $xmlFilePath it returned the first file, not the others. So, the loop isnt running. I have attempted many other ways to tackle this task, but nothing seems to be working. I cannot even echo the $xml. When I try to, it returns nothing.
XML file looks like then when opened except x5:
<GetMatchingProductForIdResult Id="082686322638" IdType="UPC" status="Success">
<Products>
<Product>
<Identifiers>
<MarketplaceASIN>
<MarketplaceId>ATVPDKIKX0DER</MarketplaceId>
<ASIN>B00TU53O8Q</ASIN>
</MarketplaceASIN>
</Identifiers>
<AttributeSets>
<ns2:ItemAttributes xmlns:ns2="http://mws.amazonservices.com/schema/Products/2011-10-01/default.xsd" xml:lang="en-US">
<ns2:Binding>Toy</ns2:Binding>
<ns2:Brand>Rubie's</ns2:Brand>
<ns2:Color>BLACK</ns2:Color>
<ns2:Department>unisex-child</ns2:Department>
<ns2:Feature>Half Helmet mask accessory covers face; one size fits most</ns2:Feature>
<ns2:Feature>Officially licensed Star Wars Episode VII costume accessory; as worn by Kylo Ren in Star Wars Episode VII: The Force Awakens</ns2:Feature>
<ns2:Feature>Helmet has faux battle damage representing a pivotal moment in the movie</ns2:Feature>
<ns2:Feature>Kylo Ren costumes and additional accessories available separately</ns2:Feature>
<ns2:Feature>Rubie's offers costumes and accessories from Star Wars original and prequel trilogies as well as the Clone Wars series; great group and family costume ideas</ns2:Feature>
<ns2:ItemDimensions>
<ns2:Height Units="inches">10.00</ns2:Height>
<ns2:Length Units="inches">10.00</ns2:Length>
<ns2:Width Units="inches">10.00</ns2:Width>
<ns2:Weight Units="pounds">0.13</ns2:Weight>
</ns2:ItemDimensions>
<ns2:IsAdultProduct>false</ns2:IsAdultProduct>
<ns2:Label>Rubies - Domestic</ns2:Label>
<ns2:ListPrice>
<ns2:Amount>9.99</ns2:Amount>
<ns2:CurrencyCode>USD</ns2:CurrencyCode>
</ns2:ListPrice>
<ns2:Manufacturer>Rubies - Domestic</ns2:Manufacturer>
<ns2:ManufacturerMaximumAge Units="months">120.0</ns2:ManufacturerMaximumAge>
<ns2:ManufacturerMinimumAge Units="months">60.0</ns2:ManufacturerMinimumAge>
<ns2:Model>32263</ns2:Model>
<ns2:NumberOfItems>1</ns2:NumberOfItems>
<ns2:PackageDimensions>
<ns2:Height Units="inches">4.00</ns2:Height>
<ns2:Length Units="inches">9.20</ns2:Length>
<ns2:Width Units="inches">8.20</ns2:Width>
<ns2:Weight Units="pounds">0.15</ns2:Weight>
</ns2:PackageDimensions>
<ns2:PackageQuantity>1</ns2:PackageQuantity>
<ns2:PartNumber>32263</ns2:PartNumber>
<ns2:ProductGroup>Toy</ns2:ProductGroup>
<ns2:ProductTypeName>TOYS_AND_GAMES</ns2:ProductTypeName>
<ns2:Publisher>Rubies - Domestic</ns2:Publisher>
<ns2:Size>One Size</ns2:Size>
<ns2:SmallImage>
<ns2:URL>http://ecx.images-amazon.com/images/I/41XuPVJMMkL._SL75_.jpg</ns2:URL>
<ns2:Height Units="pixels">75</ns2:Height>
<ns2:Width Units="pixels">66</ns2:Width>
</ns2:SmallImage>
<ns2:Studio>Rubies - Domestic</ns2:Studio>
<ns2:Title>Star Wars: The Force Awakens Child's Kylo Ren Half Helmet</ns2:Title>
<ns2:Warranty>No Warranty</ns2:Warranty>
</ns2:ItemAttributes>
</AttributeSets>
<Relationships/>
<SalesRankings>
<SalesRank>
<ProductCategoryId>toy_display_on_website</ProductCategoryId>
<Rank>5178</Rank>
</SalesRank>
<SalesRank>
<ProductCategoryId>2229575011</ProductCategoryId>
<Rank>11</Rank>
</SalesRank>
</SalesRankings>
</Product>
</Products>
</GetMatchingProductForIdResult>
Please help?
Thanks in advance!
I have the following XML document:
<?xml version="1.0"?>
<GetMatchingProductForIdResponse xmlns="http://mws.amazonservices.com/schema/Products/2011-10-01">
<GetMatchingProductForIdResult Id="B0009VCOU4" IdType="ASIN" status="Success">
<Products xmlns="http://mws.amazonservices.com/schema/Products/2011-10-01" xmlns:ns2="http://mws.amazonservices.com/schema/Products/2011-10-01/default.xsd">
<Product>
<Identifiers>
<MarketplaceASIN>
<MarketplaceId>ATVPDKIKX0DER</MarketplaceId>
<ASIN>B0009VCOU4</ASIN>
</MarketplaceASIN>
</Identifiers>
<AttributeSets>
<ns2:ItemAttributes xml:lang="en-US">
<ns2:Binding>Electronics</ns2:Binding>
<ns2:Brand>DOBANI</ns2:Brand>
<ns2:Feature>Handcrafted Quality, Value Priced</ns2:Feature>
<ns2:Feature>Satisfaction Guaranteed! 30-Day Return Policy!</ns2:Feature>
<ns2:ItemDimensions>
<ns2:Height Units="inches">7.00</ns2:Height>
<ns2:Length Units="inches">6.00</ns2:Length>
<ns2:Width Units="inches">6.00</ns2:Width>
</ns2:ItemDimensions>
<ns2:Label>Mid-East</ns2:Label>
<ns2:ListPrice>
<ns2:Amount>9.90</ns2:Amount>
<ns2:CurrencyCode>USD</ns2:CurrencyCode>
</ns2:ListPrice>
<ns2:Manufacturer>Mid-East</ns2:Manufacturer>
<ns2:Model>BULB</ns2:Model>
<ns2:PackageDimensions>
<ns2:Height Units="inches">3.70</ns2:Height>
<ns2:Length Units="inches">8.10</ns2:Length>
<ns2:Width Units="inches">4.00</ns2:Width>
<ns2:Weight Units="pounds">0.35</ns2:Weight>
</ns2:PackageDimensions>
<ns2:PackageQuantity>1</ns2:PackageQuantity>
<ns2:PartNumber>BULB</ns2:PartNumber>
<ns2:ProductGroup>Single Detail Page Misc</ns2:ProductGroup>
<ns2:ProductTypeName>MUSICAL_INSTRUMENTS</ns2:ProductTypeName>
<ns2:Publisher>Mid-East</ns2:Publisher>
<ns2:SmallImage>
<ns2:URL>http://ecx.images-amazon.com/images/I/31Fsu5jKWsL._SL75_.jpg</ns2:URL>
<ns2:Height Units="pixels">75</ns2:Height>
<ns2:Width Units="pixels">50</ns2:Width>
</ns2:SmallImage>
<ns2:Studio>Mid-East</ns2:Studio>
<ns2:Title>Spare Rubber Bulb</ns2:Title>
</ns2:ItemAttributes>
</AttributeSets>
<Relationships/>
<SalesRankings>
<SalesRank>
<ProductCategoryId>sdp_misc_display_on_website</ProductCategoryId>
<Rank>36468</Rank>
</SalesRank>
</SalesRankings>
</Product>
</Products>
</GetMatchingProductForIdResult>
<ResponseMetadata>
<RequestId>afnapq823haeufabq2rhalhtz</RequestId>
</ResponseMetadata>
</GetMatchingProductForIdResponse>
I am trying to get the package dimensions, but none of my xpath queries work. Have tried these using PHP's built-in xpath functions and using QueryPath 3.0.0, but neither works.
This doesn't work even though XML Tree in Chrome shows it should:
/GetMatchingProductForIdResponse/GetMatchingProductForIdResult/Products/Product/AttributeSets/ns2:ItemAttributes/ns2:PackageDimensions/ns2:Height
I thought neutralizing the namespace would get rid of the problem since the above triggers a namespace error, but it does not:
/GetMatchingProductForIdResponse/GetMatchingProductForIdResult/Products/Product/AttributeSets/*[local-name()='ItemAttributes']/*[local-name()='PackageDimensions']/*[local-name()='Height']
Xpath has no default namespace. The Xpath provided by Chrome is invalid. An Xpath element expression without a namespace prefix always matches elements without a namespace.
You need to register your own namespace prefixes and use them:
$dom = new DOMDocument();
$dom->loadXml($xml);
$xpath = new DOMXpath($dom);
$xpath->registerNamespace(
'p', 'http://mws.amazonservices.com/schema/Products/2011-10-01'
);
$xpath->registerNamespace(
'pd', 'http://mws.amazonservices.com/schema/Products/2011-10-01/default.xsd'
);
$result = $xpath->evaluate(
'string(
/p:GetMatchingProductForIdResponse
/p:GetMatchingProductForIdResult
/p:Products
/p:Product
/p:AttributeSets
/pd:ItemAttributes
/pd:PackageDimensions
/pd:Height
)'
);
var_dump($result);
Output: https://eval.in/150409
string(4) "3.70"
I'm afraid even the first part of your xpath is suffering for the namespace issue. Have you tried :
/*[local-name()='GetMatchingProductForIdResponse']/*[local-name()='GetMatchingProductForIdResult']/*[local-name()='Products']/*[local-name()='Product']/*[local-name()='AttributeSets']/*[local-name()='ItemAttributes']/*[local-name()='PackageDimensions']/*[local-name()='Height']
I think to use the normal xpath approach, you will need to set the corresponding namespaces on the xpath evaluator itsself.
/**
* Convert XML to JSON and return.
*/
$response = preg_replace("/(<\/?)(\w+):([^>]*>)/", "$1$2$3", $response);
$xml = simplexml_load_string($response);
$json = json_encode($xml);
return json_decode($json,TRUE);
This worked for me
I am trying to parse xml file from amazon but found difficulties. I am using simplexml_load_string
$xml = simplexml_load_string( 'My xml here' );
but when I do
echo $xml->GetMatchingProductResult->Product->AttributeSets;
it shows nothing
How can I access the Brand value?
My xml file:
<?xml version="1.0"?>
<GetMatchingProductResponse xmlns="http://mws.amazonservices.com/schema/Products/2011-10-01">
<GetMatchingProductResult ASIN="B003IOSNNQ" status="Success">
<Product xmlns="http://mws.amazonservices.com/schema/Products/2011-10-01" xmlns:ns2="http://mws.amazonservices.com/schema/Products/2011-10-01/default.xsd">
<Identifiers>
<MarketplaceASIN>
<MarketplaceId>A1F83G8C2ARO7P</MarketplaceId>
<ASIN>B003IOSNNQ</ASIN>
</MarketplaceASIN>
</Identifiers>
<AttributeSets>
<ns2:ItemAttributes xml:lang="en-GB">
<ns2:Binding>Misc.</ns2:Binding>
<ns2:Brand>eSecure</ns2:Brand>
<ns2:Feature>Colour: Classic Black</ns2:Feature>
<ns2:Feature>Thickness: Approximately 40mm - More than msot sellers</ns2:Feature>
<ns2:Feature>Dimensions [length x width at widest and narrowest]: approximately 280 x 190 x 70mm</ns2:Feature>
<ns2:Feature>Material: Stretch Lycra, Silica Gel</ns2:Feature>
<ns2:Feature>Ideal for Standard Bicycle / Static Exercise Bike</ns2:Feature>
<ns2:Label>eSecure</ns2:Label>
<ns2:Manufacturer>eSecure</ns2:Manufacturer>
<ns2:PackageDimensions>
<ns2:Height Units="inches">2.13</ns2:Height>
<ns2:Length Units="inches">10.71</ns2:Length>
<ns2:Width Units="inches">7.72</ns2:Width>
<ns2:Weight Units="pounds">0.49</ns2:Weight>
</ns2:PackageDimensions>
<ns2:PackageQuantity>1</ns2:PackageQuantity>
<ns2:ProductGroup>Sports</ns2:ProductGroup>
<ns2:ProductTypeName>SPORTING_GOODS</ns2:ProductTypeName>
<ns2:Publisher>eSecure</ns2:Publisher>
<ns2:SmallImage>
<ns2:URL>http://ecx.images-amazon.com/images/I/41OIjmpza2L._SL75_.jpg</ns2:URL>
<ns2:Height Units="pixels">75</ns2:Height>
<ns2:Width Units="pixels">75</ns2:Width>
</ns2:SmallImage>
<ns2:Studio>eSecure</ns2:Studio>
<ns2:Title>eSecure - Extra Comfort Bike Bicycle Gel Saddle Seat Cover</ns2:Title>
</ns2:ItemAttributes>
</AttributeSets>
<Relationships/>
<SalesRankings>
<SalesRank>
<ProductCategoryId>sports_display_on_website</ProductCategoryId>
<Rank>398</Rank>
</SalesRank>
<SalesRank>
<ProductCategoryId>458338031</ProductCategoryId>
<Rank>1</Rank>
</SalesRank>
</SalesRankings>
</Product>
</GetMatchingProductResult>
<ResponseMetadata>
<RequestId>9b44aba6-d1fa-486a-8114-2bc4f9311d8d</RequestId>
</ResponseMetadata>
</GetMatchingProductResponse>
I know this is an old question but I had a hard time with the same thing.
First simplexml_load_string doesn't handle the namespaces thrown in like this, so you could go recursively and check and then load the namespaces, evaluate the xml and waste a lot of time ...
In my case I didn't care about evaluating the format of the xml with the namespaces, so I just removed them from the string with regex. After this simplexml_load_string won't omit those parts anymore and it's easy to get an array out of it with json_encode and json_decode.
//convert an xml string into an array
function xml2array($xml){
$xml = preg_replace('/(<\/?)\w+:([^>]*>)/', '$1$2', $xml); //get rid of namespaces
$xml = simplexml_load_string($xml);
return json_decode(json_encode($xml),true); //use built-in stuff
}
The only problem with this is when the xml is full of attributes containing useful data, then you would need something else instead of simplexml_load_string. Note that it returns an #attributes element from this:
<GetMatchingProductResult ASIN="B003IOSNNQ" status="Success">
but omits it from this part:
<Width Units="pixels">75</Width>
I have no idea why or how deep down it would check in the nested tags.
echo $xmlobj->children('',true)->ListMatchingProductsResult->Products->Product->AttributeSets->children('ns2',true)->ItemAttributes->Brand.PHP_EOL;