0

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>
1
  • 2
    Don't remove the xmlns attribute, it is relevant. Commented Mar 24, 2015 at 10:41

2 Answers 2

3

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));
}
Sign up to request clarification or add additional context in comments.

1 Comment

Omg, thank you so much everything works perfect now !
0

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.

4 Comments

The xml is much more complex this is just a little part of it.
In your solution you are looping through every erp_pid but i need to loop through the LINE_ITEMS. What if i need to access the description ? Then i need to create a second loop ?
And in my xml i do have a namespace but you dont see it in this littel extract.
You can of course iterate through a part of the xml if you want, just use the correct path. I made an update of my answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.