在PHP中解析带有动态名称空间前缀的XML元素


Parsing XML elements with dynamic namespace prefix in PHP

我有以下XML(可以说是SOAP请求):

<SOAPENV:Envelope xmlns:SOAPENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:NS="http://xyz.gov/headerschema" >
    <SOAPENV:Header>
        <NS:myHeader>
            <NS:SourceID>223423</NS:SourceID>
        </NS:myHeader>
    </SOAPENV:Header>
</SOAPENV:Envelope>

我使用以下代码,它运行良好:

<?php 
$myRequest ='<SOAPENV:Envelope xmlns:SOAPENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:NS="http://xyz.gov/headerschema" >
   <SOAPENV:Header>
      <NS:myHeader>
         <NS:SourceID>223423</NS:SourceID>
      </NS:myHeader>
   </SOAPENV:Header>
   </SOAPENV:Envelope>';
$xml = simplexml_load_string($myRequest, NULL, NULL, "http://schemas.xmlsoap.org/soap/envelope/");
$namespaces = $xml->getNameSpaces(true);
$soapHeader = $xml->children($namespaces['SOAPENV'])->Header;
$myHeader = $soapHeader->children($namespaces['NS'])->myHeader;
echo (string)$myHeader->SourceID;
?>

问题

我知道前缀(SOAPENV+NS),但客户端可以将前缀更改为他们想要的任何前缀,因此他们可以向我发送带有(MY-SOAPENV+MY-NS)前缀的xml文档。

我的问题

既然名称空间前缀不是静态的,我该如何处理它?我该如何解析它?

感谢

这里是另一种方式。我们可以动态解析数据,如下所示。

$myRequest ='<SOAPENV:Envelope xmlns:SOAPENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:NS="http://xyz.gov/headerschema" >
           <SOAPENV:Header>
              <NS:myHeader>
                 <NS:SourceID>223423</NS:SourceID>
              </NS:myHeader>
           </SOAPENV:Header>
           </SOAPENV:Envelope>';

$xml        = simplexml_load_string(
    $myRequest, NULL, NULL, "http://schemas.xmlsoap.org/soap/envelope/"
);
$namespaces = $xml->getNameSpaces(true);
$prefix     = array_keys($namespaces); // we getting all namespaces here. According 
                                       // to that we can find datas.
$soapHeader = $xml->children($namespaces[$prefix[0]])->Header;
$myHeader   = $soapHeader->children($namespaces[$prefix[1]])->myHeader;
echo (string)$myHeader->SourceID;

您应该使用DOM——就我个人而言,我认为这在一般情况下是正确的,因为"简单XML"是一种矛盾修辞法,但我知道其他人不同意。在处理像SOAP这样的复杂文档树时,这当然是正确的。

DOM提供了getElementsByTagNameNS()(以及其他相关的NS定位方法),允许您指定命名空间URI(即应该保持静态并提前知道的东西),而不是特定于前缀。

$soapNsUri = 'http://schemas.xmlsoap.org/soap/envelope/';
$myNsUri = 'http://xyz.gov/headerschema';
$doc = new DOMDocument;
$doc->loadXML($myRequest);
$header = $doc->getElementsByTagNameNS($soapNsUri, 'Header')->item(0);
$myHeader = $header->getElementsByTagNameNS($myNsUri, 'myHeader')->item(0);
$sourceID = $myHeader->getElementsByTagNameNS($myNsUri, 'SourceID')->item(0);
echo $sourceID->firstChild->data;

查看它的工作