【问题标题】:Xpath query results are always emptyXpath 查询结果始终为空
【发布时间】:2014-05-12 22:23:09
【问题描述】:

我有以下 XML 文档:

<?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>

我正在尝试获取包装尺寸,但我的 xpath 查询均不起作用。已经使用 PHP 的内置 xpath 函数和使用 QueryPath 3.0.0 尝试了这些,但都不起作用。

即使 Chrome 中的 XML 树显示它应该这样做,这也不起作用:

/GetMatchingProductForIdResponse/GetMatchingProductForIdResult/Products/Product/AttributeSets/ns2:ItemAttributes/ns2:PackageDimensions/ns2:Height

我认为中和命名空间会解决问题,因为上面会触发命名空间错误,但事实并非如此:

/GetMatchingProductForIdResponse/GetMatchingProductForIdResult/Products/Product/AttributeSets/*[local-name()='ItemAttributes']/*[local-name()='PackageDimensions']/*[local-name()='Height']

【问题讨论】:

    标签: php xml xpath


    【解决方案1】:

    Xpath 没有默认命名空间。 Chrome 提供的 Xpath 无效。没有命名空间前缀的 Xpath 元素表达式总是匹配没有命名空间的元素。

    您需要注册自己的命名空间前缀并使用它们:

    $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);
    

    输出:https://eval.in/150409

    string(4) "3.70"
    

    【讨论】:

      【解决方案2】:

      恐怕您的 xpath 的第一部分也会因命名空间问题而受到影响。你试过了吗:

      /*[local-name()='GetMatchingProductForIdResponse']/*[local-name()='GetMatchingProductForIdResult']/*[local-name()='Products']/*[local-name()='Product']/*[local-name()='AttributeSets']/*[local-name()='ItemAttributes']/*[local-name()='PackageDimensions']/*[local-name()='Height']

      我认为要使用普通的 xpath 方法,您需要在 xpath 评估器本身上设置相应的命名空间。

      【讨论】:

      • 得到预期的字段值。
      • 我认为使用更短的语法更具可读性:/*:GetMatchingProductForIdResponse/*:GetMatchingProductForIdResult/*:Products/*:Product/*:AttributeSets/*:ItemAttributes/*:PackageDimensions/*:Height
      • 根据您的上下文,您还可以考虑更简单的不太具体的查询,例如://*:Product//*:PackageDimensions
      【解决方案3】:
          /**
           * 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);
      

      这对我有用

      【讨论】:

        猜你喜欢
        • 2015-01-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-08-24
        • 2019-05-31
        • 1970-01-01
        • 2012-01-02
        • 2013-06-23
        相关资源
        最近更新 更多