将具有多个命名空间的XML解析为JSON - PHP

时间:2018-01-17 11:20:37

标签: php xml xpath simplexml

我想访问XML并将其解析为JSON。

<?xml version='1.0' encoding='UTF-8'?>
<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/' xmlns:ser='http://service.billing.org/'>
  <soapenv:Header />
  <soapenv:Body>
  <ser:processTrans>
     <xmlValue>
         <![CDATA[
            <ebpacket> 
                <head> 
                    <packettype> UserAuthorization</packettype>
                    <staffcode> ePay_UserName  </staffcode> 
                    <pwd>  ePay_Password </pwd>
                </head> 
                <body>
                    <email> _username  </email>
                    <loginpwd>  _password  </loginpwd>
                    <deviceid>  DeviceId  </deviceid>
                </body>
            </ebpacket>
        ]]>
    </xmlValue>
  </ser:processTrans>

我可以通过以下方式访问这些值:

$xml_str = str_replace(PHP_EOL, '', $xmlstr);
$xml = SimpleXML_Load_String($xml_str,'SimpleXMLElement', LIBXML_NOCDATA, "http://schemas.xmlsoap.org/soap/envelope/");
$xml->registerXPathNamespace('ser', 'http://service.billing.org');
$j_obj = json_encode($xml->xpath('//soapenv:Body'));

问题是,XML结构事先不知道。因此,我无法通过命名空间专门访问。除非我指定名称空间 $ xml-&gt; xpath(&#39; // soapenv:Body&#39;),否则它不会返回预期的结果。

1 个答案:

答案 0 :(得分:0)

我认为您将两个名称空间混淆了,您尝试使用用于soapenv的URI注册ser前缀。并不是说这会影响代码,但它可能无法满足您的期望。

至于事先不知道名称空间,在SimpleXML中,您可以使用getDocNamespaces()从文档中获取名称空间,然后循环并根据前缀注册它们。因此,以下代码获取Body的XML内容...

$xml_str = str_replace(PHP_EOL, '', $xmlstr);
$xml = simplexml_load_string($xml_str,'SimpleXMLElement', LIBXML_NOCDATA);
$ns = $xml->getDocNamespaces(true);
foreach ( $ns as $prefix => $URI )   {
    $xml->registerXPathNamespace($prefix, $URI);
}
$j_obj = json_encode($xml->xpath('//soapenv:Body/*'));