如何使用PHP从此Amazon XML响应文件中获取数据?

时间:2018-08-23 15:18:36

标签: php xml amazon-web-services amazon-mws

如何从下面显示的Amazon MWS XML文件中提取值?

可悲的是,我对PHP(或XML)不太满意。我一直在阅读/尝试在所有可以找到的所有站点上找到的所有内容,但我认为我还不能胜任这项工作。

我已经尝试过DOM,simpleXML,名称空间等,但一定是完全搞错了。

我已经尝试了以下代码段:

- (sometext) a-z,[space]A-Z

但是,它仅从最外层节点返回此数据,如下所示:

  

GetMyPriceForASINResult = xxxxxxxxxxxB07DNYLZP5USD9.97USD9.97USD0.00USD15.99AMAZONNewNewxxxxxxxxxxxxx刺青   ResponseMetadata = xxxxxxxxxxxxxxxxxxxxxxxx

我只是想获得的是[Offers]节点下子代的货币和价格。

    $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>";
    }

更新

奈杰尔(Nigel)提供的链接无济于事-它本质上是信息汇编。

1 个答案:

答案 0 :(得分:0)

XML 总体上相当容易使用,但是您偶然发现了其中一项更加棘手的事情:XML名称空间。这是由于外部元素中configuration.CreateMap<CustomerDto, Customer>() .AfterMap<CustomerAction>().ReverseMap(); public class CustomerAction : IMappingAction<CustomerDto, Customer> { private readonly IObjectMapper _objectMapper; public CustomerAction(IObjectMapper objectMapper) { _objectMapper = objectMapper; } public void Process(CustomerDto customerDto, Customer customer) { } } 属性的存在所致。

在查看您的文档时,我的第一个想法是,由于我不熟悉此API,因此“报价”听起来可能是复数形式。因此,我修改了测试文档以允许这样做,因为xmlns可能设计为包含零个,一个或多个一个<Offers>

因此,出于测试目的,它看起来像这样(为方便起见,我仅复制了一个<Offer>):

<Offer>

我使用的PHP代码如下。据我所知,我在这里使用过<?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> ,但我希望也有一个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),但名称空间仍然存在。看起来像这样:

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";