soap响应体存在Simlpexml和registerxpathnamespace问题


Simlpexml and registerxpathnamespace issue with soap response body

这是xml:(a.xml

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
     xmlns:ser="http://www.example.com/v1/services">
    <soapenv:Header/>
    <soapenv:Body>
        <ser:getAnalyticalDeliveryEstimatesRequest>
            <ser:buyer>
                <ser:buyerId>1233</ser:buyerId>
                <ser:toCountry>IN</ser:toCountry>
                <ser:toZip>110001</ser:toZip>
            </ser:buyer>
            <ser:item>
                <ser:id>25164</ser:id>
                <ser:categoryId>15032</ser:categoryId>
                <ser:seller>
                    <ser:sellerId>11997</ser:sellerId>
                    <ser:fromCountry>IN</ser:fromCountry>
                </ser:seller>
                <ser:transactionId>0</ser:transactionId>
            </ser:item>
        </ser:getAnalyticalDeliveryEstimatesRequest>
    </soapenv:Body>
</soapenv:Envelope>

解析这个的PHP代码:

$xml = simplexml_load_file( 'a.xml', NULL, NULL, 'http://schemas.xmlsoap.org/soap/envelope/');
$xml->registerXPathNamespace('soapenv', 'http://schemas.xmlsoap.org/soap/envelope/');
$xml->registerXPathNamespace('ser', 'http://www.example.com/v1/services');
$xpath = $xml->xpath( '//soapenv:Body/ser:getAnalyticalDeliveryEstimatesRequest' );
print_r($xpath);

它没有提供任何数据。

如果我做错了,请告诉我。

首先,在您的示例代码中,您实际上没有在任何地方定义$node

$xpath = $xml->xpath( '//soapenv:Body/ser:getAnalyticalDeliveryEstimatesRequest' );
print_r($node);

应为:

$xpath = $xml->xpath( '//soapenv:Body/ser:getAnalyticalDeliveryEstimatesRequest' );
$node = $xpath[0];
print_r($node);

或者:

$xpath = $xml->xpath( '//soapenv:Body/ser:getAnalyticalDeliveryEstimatesRequest' );
foreach ( $xpath as $node ) {
    print_r($node);
}

其次,print_r不擅长显示SimpleXML对象。它给你一个空的输出并不意味着元素是空的。

例如,尝试回显找到的节点的名称(Demo):

$xpath = $xml->xpath( '//soapenv:Body/ser:getAnalyticalDeliveryEstimatesRequest' );
foreach ( $xpath as $node ) {
    echo $node->getName();
}

要获取其内容,您需要使用->children()方法选择它们所在的命名空间,此时即使是print_r也可以看到它们(尽管还有其他原因不完全依赖它)(Demo):

$xpath = $xml->xpath( '//soapenv:Body/ser:getAnalyticalDeliveryEstimatesRequest' );
foreach ( $xpath as $node ) {
    print_r( $node->children('http://www.example.com/v1/services') ); 
}

请尝试搜索"带有名称空间的SimpleXML"以获取更多示例。

看到它不起作用很奇怪,但你也可以使用这个:

$dom = new DOMDocument();
$dom->loadXML($xml);
$xpath = new DOMXpath($dom);
$element = $xpath->query('//soapenv:Body/ser:getAnalyticalDeliveryEstimatesRequest');
foreach($element->item(0)->childNodes as $node) {
    // perform your actions here
}

样本输出

编辑:这也是另一种方式:

$xml_string ='<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
     xmlns:ser="http://www.example.com/v1/services">
    <soapenv:Header/>
    <soapenv:Body>
        <ser:getAnalyticalDeliveryEstimatesRequest>
            <ser:buyer>
                <ser:buyerId>1233</ser:buyerId>
                <ser:toCountry>IN</ser:toCountry>
                <ser:toZip>110001</ser:toZip>
            </ser:buyer>
            <ser:item>
                <ser:id>25164</ser:id>
                <ser:categoryId>15032</ser:categoryId>
                <ser:seller>
                    <ser:sellerId>11997</ser:sellerId>
                    <ser:fromCountry>IN</ser:fromCountry>
                </ser:seller>
                <ser:transactionId>0</ser:transactionId>
            </ser:item>
        </ser:getAnalyticalDeliveryEstimatesRequest>
    </soapenv:Body>
</soapenv:Envelope>';
$xml = simplexml_load_string($xml_string, null, null, 'http://schemas.xmlsoap.org/soap/envelope/');
$ns = $xml->getNamespaces(true);
$soap = $xml->children($ns['soapenv']);
foreach($soap->Body as $nodes) {
    $ser = $nodes->children($ns['ser'])->getAnalyticalDeliveryEstimatesRequest;
    foreach($ser->buyer as $sub_nodes) { // this can also be ->item as well
    }
}
相关文章:
  • 没有找到相关文章