dougan4663
dougan4663
2015-03-24 09:50
采纳率: 0%
浏览 45

PHP xpath在foreach循环中按属性获取元素

im am trying to loop through all the LINE_ITEMS and it works fine but in the foreach-loop im trying to access the single LINE_ITEM by attribute by using xpath but i don't get any result. Does anyone know the problem ?

 foreach($items = $xmlData->xpath('//zw:LINE_ITEM') as $item) {
    $item->xpath('//namespace:PID[@type="erp_pid"]'); No result
}
$xmlData->xpath('//zw:LINE_ITEM') 

works fine i get all LINE_ITEMS but when i try to do some xpath on the item i don't get any result.

How can i access the PID value of for example "erp_pid" ?

<?xml version="1.0" encoding="UTF-8"?>
<NM_DOCS>
    <NM_DOC>
        <DOCUMENT qualifier="default" role="original" test="false" type="orders">
            <VERSION>4.0</VERSION>
            <HEADER>
                <CONTROL_INFO>
                    <LAST_SAVE_DATE>2015-03-18T13:44:32+01:00</LAST_SAVE_DATE>
                    <PROCESS_TYPE>silent</PROCESS_TYPE>
                    <SOURCE>sales</SOURCE>

                </CONTROL_INFO>
                <SOURCING_INFO>
                    <REFERENCES>
                        <REFERENCE type="order_nexmart">
                            <ID>109546063</ID>
                            <DATES>
                                <DATE type="order">2015-03-18T13:44:30+01:00</DATE>
                            </DATES>
                        </REFERENCE>
                    </REFERENCES>
                </SOURCING_INFO>
                <DOCUMENT_INFO>
                    <DOCUMENT_ID>Test bestellnummer</DOCUMENT_ID>
                    <DATES>
                        <DATE type="delivery_ordered">2015-04-19T12:41:41+02:00</DATE>
                    </DATES>
                    <PARTIES>
                        <PARTY type="buyer">
                            <BUSINESS_ROLE>commercial</BUSINESS_ROLE>
                            <PORTAL_ID>BDE600028</PORTAL_ID>
                            <ADDITIONAL_IDS>                             
                            </ADDITIONAL_IDS>
                            <ADDRESS>                                
                            </ADDRESS>
                            <CONTACT_DETAILS>                                
                                <ACCOUNTS>
                                    <ID type="emart">sales.nexmart</ID>
                                </ACCOUNTS>
                            </CONTACT_DETAILS>
                        </PARTY>
                        <PARTY type="supplier">
                            <BUSINESS_ROLE>commercial</BUSINESS_ROLE>
                            <PORTAL_ID>zweygart_app_de</PORTAL_ID>
                            <ADDITIONAL_IDS>

                            </ADDITIONAL_IDS>
                            <ADDRESS>

                            </ADDRESS>
                            <CONTACT_DETAILS>

                            </CONTACT_DETAILS>
                        </PARTY>
                        <PARTY type="delivery">
                            <BUSINESS_ROLE>commercial</BUSINESS_ROLE>
                            <ADDRESS>

                            </ADDRESS>
                            <CONTACT_DETAILS>

                            </CONTACT_DETAILS>
                        </PARTY>
                        <PARTY type="invoice_recipient">
                            <ADDRESS>

                            </ADDRESS>
                            <CONTACT_DETAILS>

                            </CONTACT_DETAILS>
                        </PARTY>
                    </PARTIES>                    
                    <REMARKS>
                        <REMARK type="order">Test bemerkung</REMARK>
                    </REMARKS>
                </DOCUMENT_INFO>
            </HEADER>
            <LINE_ITEMS>
                <LINE_ITEM>                    
                    <PRODUCT_ID>
                        <SUPPLIER_PID>119556</SUPPLIER_PID>
                        <GTIN>4030646269130</GTIN>
                        <ADDITIONAL_PIDS>
                            <PID type="supplier_pid_original">119556</PID>
                            <PID type="gtin_original">4030646269130</PID>
                            <PID type="erp_pid">119556</PID>
                        </ADDITIONAL_PIDS>
                        <DESCRIPTIONS>
                            <DESCR type="short">short desc</DESCR>
                            <DESCR type="short_original">some text</DESCR>
                        </DESCRIPTIONS>
                    </PRODUCT_ID>                    
                </LINE_ITEM>
                <LINE_ITEM>                    
                    <PRODUCT_ID>
                        <SUPPLIER_PID>123456789</SUPPLIER_PID>
                        <GTIN>123456789</GTIN>
                        <ADDITIONAL_PIDS>
                            <PID type="supplier_pid_original">123456</PID>
                            <PID type="gtin_original">123456</PID>
                            <PID type="erp_pid">123456</PID>
                        </ADDITIONAL_PIDS>
                        <DESCRIPTIONS>
                            <DESCR type="short">short desc</DESCR>
                            <DESCR type="short_original">Some description</DESCR>
                        </DESCRIPTIONS>
                    </PRODUCT_ID>                                       

                </LINE_ITEM>
            </LINE_ITEMS>

        </DOCUMENT>
    </NM_DOC>
</NM_DOCS>
  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

2条回答 默认 最新

  • duanou3868
    duanou3868 2015-03-24 10:40
    已采纳

    The problem is not XPath but SimpleXML. SimpleXMLElement::xpath() is limited. It converts the result into an array of SimpleXMLElement objects, but here are other nodes in a DOM. More important you will have to register the namespaces on each new SimpleXMLElement again.

    $element = new SimpleXMLElement($xml);
    $element->registerXPathNamespace('namespace', 'urn:foo');
    
    foreach($element->xpath('//namespace:LINE_ITEMS/namespace:LINE_ITEM') as $item) {
      $item->registerXPathNamespace('namespace', 'urn:foo');
      var_dump((string)$item->xpath('.//namespace:PID[@type="erp_pid"]')[0]);
    }
    

    Output:

    string(6) "119556"
    string(6) "123456"
    

    You might notice that I prefixed your detail expression with an .. A slash at the start of the expression always makes it relative to the document itself, not the current node. The . represents the current node.

    If you use DOM directly, you create a separate DOMXPath object and register the namespaces on this object. Additionally you can use XPath expressions that return scalar values.

    $dom = new DOMDocument();
    $dom->loadXml($xml);
    $xpath = new DOMXPath($dom);
    $xpath->registerNamespace('namespace', 'urn:foo');
    foreach($xpath->evaluate('//namespace:LINE_ITEMS/namespace:LINE_ITEM') as $node) {
      var_dump($xpath->evaluate('string(.//namespace:PID[@type="erp_pid"])', $node));
    }
    
    点赞 评论
  • douni1396
    douni1396 2015-03-24 10:06

    This works for me:

    foreach($xmlData->LINE_ITEM as $item) {
        $erp = ( $item->xpath('//PID[@type="erp_pid"]'));
        foreach($erp as $v) {
            echo $v. " / ";
        }
    }
    

    Just remove the namespace in your xpath, your xml doesn't use a namespace.

    If you want to iterate through a part of the xml be sure to use the correct path.

    点赞 评论

相关推荐