0

Is there a simple way to parse tags that have colons in the tag name using SimpleXML xpath?

Example:

<v12:ProcessShipmentResponse>SUCCESS</v12:ProcessShipmentResponse>

Here is the code that I use to parse tags that are not namespaced but breaks with namespaced tags.

    $xml = simplexml_load_string($responseXMLL, NULL, NULL, 'http://schemas.xmlsoap.org/soap/envelope/');


    foreach ($xml->xpath('soapenv:Body') as $body) {


        $custInfoArr['status'] = (string) $body->v12:ProcessShipmentReply->v12:HighestSeverity;
        $custInfoArr['trackingCode'] = (string) $body->v12:ProcessShipmentReply->v12:CompletedShipmentDetail->v12:CompletedPackageDetails->v12:TrackingIds->v12:TrackingNumber;
        $custInfoArr['labelCode'] = (string) $body->v12:ProcessShipmentReply->v12:CompletedShipmentDetail->v12:CompletedPackageDetails->v12:Label->v12:Parts->v12:Image;

    }
0

3 Answers 3

0

Take a look to this.

 public bool SimpleXMLElement::registerXPathNamespace(string $prefix,string $ns);

From php manual:

Creates a prefix/ns context for the next XPath query. In particular, this is helpful if the provider of the given XML document alters the namespace prefixes. registerXPathNamespace will create a prefix for the associated namespace, allowing one to access nodes in that namespace without the need to change code to allow for the new prefixes dictated by the provider.

Sign up to request clarification or add additional context in comments.

3 Comments

This is only relevant to using XPath, not the normal object and array-style access provided by SimpleXML (->node and ['attribute']).
Yes, but you didn't really explain how to use it, making it seem like this was how to fix the OP's code, which other than one line was not using XPath, and doesn't need to.
@DonCallisto: You don't need to register prefixes in SimpleXML that are already registered. Also it's better to suggest selecting ProcessShipmentReply element directly, therefore the prefix is out-of-the way inside the foreach. It's really not a useful answer, so perhaps this is why DVs appear. Especially (I must admit) this is a dupe of a dupe of a dupe.
0

This has been asked many times before. Those are not "tags with colons", they are XML namespaces, and require special handling in any parser.

In the case of SimpleXML, this is provided by the ->children() and ->attributes() methods.

You can either rely on the alias/prefix not changing (there is no guarantee of this, as the "semantics" of the XML document will not change) and use true as the second parameter (in your case $body->children('v12', TRUE)) or set a constant for the namespace URI (which is guaranteed not to change) and pass that (in your case define('XMLNS_FEDEX_V12', 'http://fedex.com/ws/ship/v12'); /* ... */ $body->children(XMLNS_FEDEX_V12)).

Comments

-1

Needed to register namespaces like this. Here is a working example in case someone needs it.

        $xml = simplexml_load_string($result, NULL, NULL, 'http://schemas.xmlsoap.org/soap/envelope/');
        $xml->registerXPathNamespace('env', 'http://schemas.xmlsoap.org/soap/envelope/');
        $xml->registerXPathNamespace('v12', 'http://fedex.com/ws/ship/v12');
        $bodies = $xml->xpath('env:Body');

        foreach($bodies as $body){

          $reply = $body->children('v12', TRUE)->ProcessShipmentReply;
          $custInfoArr['status'] = (string) $reply->HighestSeverity;
          $custInfoArr['trackingCode'] = (string) $reply->CompletedShipmentDetail->CompletedPackageDetails->TrackingIds->TrackingNumber;
          $custInfoArr['labelCode'] = (string) $reply->CompletedShipmentDetail->CompletedPackageDetails->Label->Parts->Image;


        }

1 Comment

registerXPathNamespace is only necessary if you are using ->xpath(). The ->children() method is based purely on the XML itself.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.