我如何使用 PHP 从这个 Amazon XML 响应文件中获取数据?
How can I get data from this Amazon XML response file using PHP?
如何从如下所示的亚马逊 MWS XML 文件中提取值?
遗憾的是我不太擅长 PHP(或 XML)。我已经 reading/trying 在我能找到的所有网站上找到了所有我能找到的东西,但我认为我只是不能胜任这份工作。
我试过DOM、简单XML、命名空间等等,但一定是完全搞错了。
我试过这段代码:
$response = $service->GetMyPriceForASIN($request);
$dom = new DOMDocument();
$dom->loadXML($response->toXML());
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
$dom->saveXML();
$x = $dom->documentElement;
foreach ($x->childNodes AS $item) {
print $item->nodeName . " = " . $item->nodeValue . "<br>";
}
然而,它仅 returns 来自最外层节点的数据,如下所示:
GetMyPriceForASINResult = xxxxxxxxxxxB07DNYLZP5USD9.97USD9.97USD0.00USD15.99AMAZONNewNewxxxxxxxxxxxxxDazzle Tattoos
ResponseMetadata = xxxxxxxxxxxxxxxxxxxxxxxx
我只是想获取 [Offers] 节点下子节点的货币和价格。
<?xml version="1.0"?>
<GetMyPriceForASINResponse
xmlns="http://mws.amazonservices.com/schema/Products/2011-10-01">
<GetMyPriceForASINResult ASIN="B07DNYLZP5" status="Success">
<Product>
<Identifiers>
<MarketplaceASIN>
<MarketplaceId>xxxxxxxxxxxxxxxxxx</MarketplaceId>
<ASIN>B07DNYLZP5</ASIN>
</MarketplaceASIN>
</Identifiers>
<Offers>
<Offer>
<BuyingPrice>
<LandedPrice>
<CurrencyCode>USD</CurrencyCode>
<Amount>9.97</Amount>
</LandedPrice>
<ListingPrice>
<CurrencyCode>USD</CurrencyCode>
<Amount>9.97</Amount>
</ListingPrice>
<Shipping>
<CurrencyCode>USD</CurrencyCode>
<Amount>0.00</Amount>
</Shipping>
</BuyingPrice>
<RegularPrice>
<CurrencyCode>USD</CurrencyCode>
<Amount>15.99</Amount>
</RegularPrice>
<FulfillmentChannel>AMAZON</FulfillmentChannel>
<ItemCondition>New</ItemCondition>
<ItemSubCondition>New</ItemSubCondition>
<SellerId>xxxxxxxxxx</SellerId>
<SellerSKU>Dazzle Tattoos</SellerSKU>
</Offer>
</Offers>
</Product>
</GetMyPriceForASINResult>
<ResponseMetadata>
<RequestId>xxxxxxxxxxxxxxxxxxxxx</RequestId>
</ResponseMetadata>
</GetMyPriceForASINResponse>
更新
Nigel 提供的 link 没有帮助 - 它基本上是信息概要。
XML 一般来说, 相当容易使用,但是您偶然发现了使它变得更加棘手的事情之一:XML名称空间。这是由外部元素中 xmlns
属性的存在给出的。
我看到您的文档时的第一个想法是,由于我不熟悉这个 API,所以 "offers" 听起来可能是复数。因此,我修改了测试文档以允许这样做,因为 <Offers>
可能被设计为包含零个、一个或多个 <Offer>
.
因此,出于测试目的,它看起来像这样(为了方便,我刚刚复制了单个 <Offer>
):
<?xml version="1.0"?>
<GetMyPriceForASINResponse
xmlns="http://mws.amazonservices.com/schema/Products/2011-10-01"
>
<GetMyPriceForASINResult ASIN="B07DNYLZP5" status="Success">
<Product>
<Identifiers>
<MarketplaceASIN>
<MarketplaceId>xxxxxxxxxxxxxxxxxx</MarketplaceId>
<ASIN>B07DNYLZP5</ASIN>
</MarketplaceASIN>
</Identifiers>
<Offers>
<Offer>
<BuyingPrice>
<LandedPrice>
<CurrencyCode>USD</CurrencyCode>
<Amount>9.97</Amount>
</LandedPrice>
<ListingPrice>
<CurrencyCode>USD</CurrencyCode>
<Amount>9.97</Amount>
</ListingPrice>
<Shipping>
<CurrencyCode>USD</CurrencyCode>
<Amount>0.00</Amount>
</Shipping>
</BuyingPrice>
<RegularPrice>
<CurrencyCode>USD</CurrencyCode>
<Amount>15.99</Amount>
</RegularPrice>
<FulfillmentChannel>AMAZON</FulfillmentChannel>
<ItemCondition>New</ItemCondition>
<ItemSubCondition>New</ItemSubCondition>
<SellerId>xxxxxxxxxx</SellerId>
<SellerSKU>Dazzle Tattoos</SellerSKU>
</Offer>
<Offer>
<BuyingPrice>
<LandedPrice>
<CurrencyCode>USD</CurrencyCode>
<Amount>9.97</Amount>
</LandedPrice>
<ListingPrice>
<CurrencyCode>USD</CurrencyCode>
<Amount>9.97</Amount>
</ListingPrice>
<Shipping>
<CurrencyCode>USD</CurrencyCode>
<Amount>0.00</Amount>
</Shipping>
</BuyingPrice>
<RegularPrice>
<CurrencyCode>USD</CurrencyCode>
<Amount>15.99</Amount>
</RegularPrice>
<FulfillmentChannel>AMAZON</FulfillmentChannel>
<ItemCondition>New</ItemCondition>
<ItemSubCondition>New</ItemSubCondition>
<SellerId>xxxxxxxxxx</SellerId>
<SellerSKU>Dazzle Tattoos</SellerSKU>
</Offer>
</Offers>
</Product>
</GetMyPriceForASINResult>
<ResponseMetadata>
<RequestId>xxxxxxxxxxxxxxxxxxxxx</RequestId>
</ResponseMetadata>
</GetMyPriceForASINResponse>
我使用的PHP代码如下。我在这里使用了 SimpleXML
,因为我很熟悉它,但我希望也会有一个 DOMDocument
解决方案。
<?php
$file = 'prices.xml';
$doc = simplexml_load_file($file);
// Examine the namespaces
$namespaces = $doc->getNamespaces(true);
print_r($namespaces);
$nsDoc = $doc->children($namespaces['']);
$nsDoc->registerXPathNamespace('p', 'http://mws.amazonservices.com/schema/Products/2011-10-01');
$nodes = $nsDoc->xpath('//p:GetMyPriceForASINResult/p:Product/p:Offers/p:Offer');
foreach ($nodes as $node)
{
print_r($node);
}
我的第一个 print_r
将向您展示文档中的命名空间,而您唯一拥有的是 null 命名空间。由于这是空的,您的标签没有前缀字符串(例如 Amazon:Product
),但命名空间仍然存在。看起来像这样:
Array
(
[] => http://mws.amazonservices.com/schema/Products/2011-10-01
)
然后我得到文档的命名空间版本 ($doc->children($namespaces[''])
) 来使用。我还将命名空间的名称声明为 p
(使用 registerXPathNamespace
),这是一个任意名称 - 您可以在此处使用任何对您有意义的名称。 (我确实尝试注册一个空名称 (''
),但这没有用)。
最后,我按照评论中的建议使用了 XPath,但由于命名空间适用于父项及其所有子项,因此我在每个标记前添加了我的命名空间别名。 (XPath 基本上是 XML 的一种查询语言,对它的解释需要一本书或一本手册,所以我不会在这里深入挖掘。如果你打算做的不仅仅是粗略的XML,我建议在网络上找到一个 XML 测试应用程序并尝试一些查询。
输出产生两个(相同的)<Offer>
节点,因此:
SimpleXMLElement Object
(
[BuyingPrice] => SimpleXMLElement Object
(
[LandedPrice] => SimpleXMLElement Object
(
[CurrencyCode] => USD
[Amount] => 9.97
)
[ListingPrice] => SimpleXMLElement Object
(
[CurrencyCode] => USD
[Amount] => 9.97
)
[Shipping] => SimpleXMLElement Object
(
[CurrencyCode] => USD
[Amount] => 0.00
)
)
[RegularPrice] => SimpleXMLElement Object
(
[CurrencyCode] => USD
[Amount] => 15.99
)
[FulfillmentChannel] => AMAZON
[ItemCondition] => New
[ItemSubCondition] => New
[SellerId] => xxxxxxxxxx
[SellerSKU] => Dazzle Tattoos
)
SimpleXMLElement Object
(
[BuyingPrice] => SimpleXMLElement Object
(
[LandedPrice] => SimpleXMLElement Object
(
[CurrencyCode] => USD
[Amount] => 9.97
)
[ListingPrice] => SimpleXMLElement Object
(
[CurrencyCode] => USD
[Amount] => 9.97
)
[Shipping] => SimpleXMLElement Object
(
[CurrencyCode] => USD
[Amount] => 0.00
)
)
[RegularPrice] => SimpleXMLElement Object
(
[CurrencyCode] => USD
[Amount] => 15.99
)
[FulfillmentChannel] => AMAZON
[ItemCondition] => New
[ItemSubCondition] => New
[SellerId] => xxxxxxxxxx
[SellerSKU] => Dazzle Tattoos
)
您也需要取消引用每个节点中的项目。为此,您可以使用对象引用,然后转换为您想要的类型。例如:
$fulfillment = (string) $node->FulfillmentChannel;
echo "$fulfillment\n";
在循环中,这将产生我们期望的值:
AMAZON
AMAZON
如何从如下所示的亚马逊 MWS XML 文件中提取值?
遗憾的是我不太擅长 PHP(或 XML)。我已经 reading/trying 在我能找到的所有网站上找到了所有我能找到的东西,但我认为我只是不能胜任这份工作。
我试过DOM、简单XML、命名空间等等,但一定是完全搞错了。
我试过这段代码:
$response = $service->GetMyPriceForASIN($request);
$dom = new DOMDocument();
$dom->loadXML($response->toXML());
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
$dom->saveXML();
$x = $dom->documentElement;
foreach ($x->childNodes AS $item) {
print $item->nodeName . " = " . $item->nodeValue . "<br>";
}
然而,它仅 returns 来自最外层节点的数据,如下所示:
GetMyPriceForASINResult = xxxxxxxxxxxB07DNYLZP5USD9.97USD9.97USD0.00USD15.99AMAZONNewNewxxxxxxxxxxxxxDazzle Tattoos ResponseMetadata = xxxxxxxxxxxxxxxxxxxxxxxx
我只是想获取 [Offers] 节点下子节点的货币和价格。
<?xml version="1.0"?>
<GetMyPriceForASINResponse
xmlns="http://mws.amazonservices.com/schema/Products/2011-10-01">
<GetMyPriceForASINResult ASIN="B07DNYLZP5" status="Success">
<Product>
<Identifiers>
<MarketplaceASIN>
<MarketplaceId>xxxxxxxxxxxxxxxxxx</MarketplaceId>
<ASIN>B07DNYLZP5</ASIN>
</MarketplaceASIN>
</Identifiers>
<Offers>
<Offer>
<BuyingPrice>
<LandedPrice>
<CurrencyCode>USD</CurrencyCode>
<Amount>9.97</Amount>
</LandedPrice>
<ListingPrice>
<CurrencyCode>USD</CurrencyCode>
<Amount>9.97</Amount>
</ListingPrice>
<Shipping>
<CurrencyCode>USD</CurrencyCode>
<Amount>0.00</Amount>
</Shipping>
</BuyingPrice>
<RegularPrice>
<CurrencyCode>USD</CurrencyCode>
<Amount>15.99</Amount>
</RegularPrice>
<FulfillmentChannel>AMAZON</FulfillmentChannel>
<ItemCondition>New</ItemCondition>
<ItemSubCondition>New</ItemSubCondition>
<SellerId>xxxxxxxxxx</SellerId>
<SellerSKU>Dazzle Tattoos</SellerSKU>
</Offer>
</Offers>
</Product>
</GetMyPriceForASINResult>
<ResponseMetadata>
<RequestId>xxxxxxxxxxxxxxxxxxxxx</RequestId>
</ResponseMetadata>
</GetMyPriceForASINResponse>
更新
Nigel 提供的 link 没有帮助 - 它基本上是信息概要。
XML 一般来说, 相当容易使用,但是您偶然发现了使它变得更加棘手的事情之一:XML名称空间。这是由外部元素中 xmlns
属性的存在给出的。
我看到您的文档时的第一个想法是,由于我不熟悉这个 API,所以 "offers" 听起来可能是复数。因此,我修改了测试文档以允许这样做,因为 <Offers>
可能被设计为包含零个、一个或多个 <Offer>
.
因此,出于测试目的,它看起来像这样(为了方便,我刚刚复制了单个 <Offer>
):
<?xml version="1.0"?>
<GetMyPriceForASINResponse
xmlns="http://mws.amazonservices.com/schema/Products/2011-10-01"
>
<GetMyPriceForASINResult ASIN="B07DNYLZP5" status="Success">
<Product>
<Identifiers>
<MarketplaceASIN>
<MarketplaceId>xxxxxxxxxxxxxxxxxx</MarketplaceId>
<ASIN>B07DNYLZP5</ASIN>
</MarketplaceASIN>
</Identifiers>
<Offers>
<Offer>
<BuyingPrice>
<LandedPrice>
<CurrencyCode>USD</CurrencyCode>
<Amount>9.97</Amount>
</LandedPrice>
<ListingPrice>
<CurrencyCode>USD</CurrencyCode>
<Amount>9.97</Amount>
</ListingPrice>
<Shipping>
<CurrencyCode>USD</CurrencyCode>
<Amount>0.00</Amount>
</Shipping>
</BuyingPrice>
<RegularPrice>
<CurrencyCode>USD</CurrencyCode>
<Amount>15.99</Amount>
</RegularPrice>
<FulfillmentChannel>AMAZON</FulfillmentChannel>
<ItemCondition>New</ItemCondition>
<ItemSubCondition>New</ItemSubCondition>
<SellerId>xxxxxxxxxx</SellerId>
<SellerSKU>Dazzle Tattoos</SellerSKU>
</Offer>
<Offer>
<BuyingPrice>
<LandedPrice>
<CurrencyCode>USD</CurrencyCode>
<Amount>9.97</Amount>
</LandedPrice>
<ListingPrice>
<CurrencyCode>USD</CurrencyCode>
<Amount>9.97</Amount>
</ListingPrice>
<Shipping>
<CurrencyCode>USD</CurrencyCode>
<Amount>0.00</Amount>
</Shipping>
</BuyingPrice>
<RegularPrice>
<CurrencyCode>USD</CurrencyCode>
<Amount>15.99</Amount>
</RegularPrice>
<FulfillmentChannel>AMAZON</FulfillmentChannel>
<ItemCondition>New</ItemCondition>
<ItemSubCondition>New</ItemSubCondition>
<SellerId>xxxxxxxxxx</SellerId>
<SellerSKU>Dazzle Tattoos</SellerSKU>
</Offer>
</Offers>
</Product>
</GetMyPriceForASINResult>
<ResponseMetadata>
<RequestId>xxxxxxxxxxxxxxxxxxxxx</RequestId>
</ResponseMetadata>
</GetMyPriceForASINResponse>
我使用的PHP代码如下。我在这里使用了 SimpleXML
,因为我很熟悉它,但我希望也会有一个 DOMDocument
解决方案。
<?php
$file = 'prices.xml';
$doc = simplexml_load_file($file);
// Examine the namespaces
$namespaces = $doc->getNamespaces(true);
print_r($namespaces);
$nsDoc = $doc->children($namespaces['']);
$nsDoc->registerXPathNamespace('p', 'http://mws.amazonservices.com/schema/Products/2011-10-01');
$nodes = $nsDoc->xpath('//p:GetMyPriceForASINResult/p:Product/p:Offers/p:Offer');
foreach ($nodes as $node)
{
print_r($node);
}
我的第一个 print_r
将向您展示文档中的命名空间,而您唯一拥有的是 null 命名空间。由于这是空的,您的标签没有前缀字符串(例如 Amazon:Product
),但命名空间仍然存在。看起来像这样:
Array
(
[] => http://mws.amazonservices.com/schema/Products/2011-10-01
)
然后我得到文档的命名空间版本 ($doc->children($namespaces[''])
) 来使用。我还将命名空间的名称声明为 p
(使用 registerXPathNamespace
),这是一个任意名称 - 您可以在此处使用任何对您有意义的名称。 (我确实尝试注册一个空名称 (''
),但这没有用)。
最后,我按照评论中的建议使用了 XPath,但由于命名空间适用于父项及其所有子项,因此我在每个标记前添加了我的命名空间别名。 (XPath 基本上是 XML 的一种查询语言,对它的解释需要一本书或一本手册,所以我不会在这里深入挖掘。如果你打算做的不仅仅是粗略的XML,我建议在网络上找到一个 XML 测试应用程序并尝试一些查询。
输出产生两个(相同的)<Offer>
节点,因此:
SimpleXMLElement Object
(
[BuyingPrice] => SimpleXMLElement Object
(
[LandedPrice] => SimpleXMLElement Object
(
[CurrencyCode] => USD
[Amount] => 9.97
)
[ListingPrice] => SimpleXMLElement Object
(
[CurrencyCode] => USD
[Amount] => 9.97
)
[Shipping] => SimpleXMLElement Object
(
[CurrencyCode] => USD
[Amount] => 0.00
)
)
[RegularPrice] => SimpleXMLElement Object
(
[CurrencyCode] => USD
[Amount] => 15.99
)
[FulfillmentChannel] => AMAZON
[ItemCondition] => New
[ItemSubCondition] => New
[SellerId] => xxxxxxxxxx
[SellerSKU] => Dazzle Tattoos
)
SimpleXMLElement Object
(
[BuyingPrice] => SimpleXMLElement Object
(
[LandedPrice] => SimpleXMLElement Object
(
[CurrencyCode] => USD
[Amount] => 9.97
)
[ListingPrice] => SimpleXMLElement Object
(
[CurrencyCode] => USD
[Amount] => 9.97
)
[Shipping] => SimpleXMLElement Object
(
[CurrencyCode] => USD
[Amount] => 0.00
)
)
[RegularPrice] => SimpleXMLElement Object
(
[CurrencyCode] => USD
[Amount] => 15.99
)
[FulfillmentChannel] => AMAZON
[ItemCondition] => New
[ItemSubCondition] => New
[SellerId] => xxxxxxxxxx
[SellerSKU] => Dazzle Tattoos
)
您也需要取消引用每个节点中的项目。为此,您可以使用对象引用,然后转换为您想要的类型。例如:
$fulfillment = (string) $node->FulfillmentChannel;
echo "$fulfillment\n";
在循环中,这将产生我们期望的值:
AMAZON
AMAZON