在PHP中使用SimpleXML xpath解析带有冒号的标签


Parse tags with colons using SimpleXML xpath in PHP

是否有一种简单的方法来解析在使用SimpleXML xpath的标签名称中有冒号的标签?

例子:

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

下面是我用来解析没有命名空间但与命名空间标记分隔的标记的代码。

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

看看这个

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

From php manual:

为下一个XPath查询创建一个前缀/ns上下文。特别是,如果给定XML文档的提供者更改了名称空间前缀。registerXPathNamespace将创建一个前缀关联的名称空间,允许访问其中的节点名称空间,而不需要更改代码以允许新的由提供者指定的前缀。

这个问题以前已经问过很多次了。这些不是"带冒号的标签",它们是XML名称空间,需要在任何解析器中进行特殊处理。

对于SimpleXML,这是由->children()->attributes()方法提供的。

您可以依赖于别名/前缀不改变(没有保证这一点,因为XML文档的"语义"不会改变),并使用true作为第二个参数(在您的情况下$body->children('v12', TRUE))或为命名空间URI设置一个常量(保证不改变)并传递它(在您的情况下define('XMLNS_FEDEX_V12', 'http://fedex.com/ws/ship/v12'); /* ... */ $body->children(XMLNS_FEDEX_V12))。

需要像这样注册名称空间。下面是一个工作示例,以防有人需要它。

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

        }
相关文章: