Parsing XML with multiple namespaces

2019-03-06 12:17发布

So I wanted to parse this XML:

<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <soapenv:Body>
    <requestContactResponse xmlns="http://webservice.foo.com">
      <requestContactReturn>
        <errorCode xsi:nil="true"/>
        <errorDesc xsi:nil="true"/>
        <id>744</id>
      </requestContactReturn>
    </requestContactResponse>
  </soapenv:Body>
</soapenv:Envelope>

Specifically I want to get the value of the tag <id>

This is what I tried:

$dom = new DOMDocument;
$dom->loadXML($xml);
$dom->children('soapenv', true)->Envelope->children('soapenv', true)->Body->children()->requestContactResponse->requestContactReturn->id;

But I get this error message:

PHP Fatal error: Call to undefined method DOMDocument::children()

I've also tried to use simpleXML:

$sxe = new SimpleXMLElement($xml);
$sxe->children('soapenv', true)->Envelope->children('soapenv', true)->Body->children()->requestContactResponse->requestContactReturn->id;

But I get this other error message:

PHP Fatal error: Call to a member function children() on a non-object

Last solution I've tried:

$sxe = new SimpleXMLElement($xml);
$elements = $sxe->children("soapenv", true)->Body->requestContactResponse->requestContactReturn;

foreach($elements as $element) {
    echo "|-$element->id-|";
}

This time the error message was:

Invalid argument supplied for foreach() 

Any suggestions?

1条回答
走好不送
2楼-- · 2019-03-06 13:15

The poorly documented fact in play here is that when you select a namespace with ->children, it remains in effect for descendent nodes.

So when you ask for $sxe->children("soapenv", true)->Body->requestContactResponse, SimpleXML assumes you are still talking about the "soapenv" namespace, so is looking for the element <soapenv:requestContactResponse>, which doesn't exist.

To switch back to the default namespace, you need to call ->children again, with a NULL namespace:

$sx->children("soapenv", true)->Body->children(NULL)->requestContactResponse->requestContactReturn->id
查看更多
登录 后发表回答