PHP simpleXML:处理SOAP请求中的未知命名空间

bep*_*ter 4 php soap namespaces simplexml

有一 现有 问题,关于PHP的SimpleXML和处理XML名称空间.我所看到的所有问题都提出了一个基本假设:代码事先知道将在传入的SOAP请求中包含哪些命名空间.就我而言,我在SOAP请求中看到了不一致的命名空间.

具体来说,我一直在努力实现一个Web服务来与Quickbooks Web Connector(pdf)交谈,我看到的一些示例请求如下所示:

<soapenv:Envelope 
 xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
 xmlns:dev="http://developer.intuit.com/">
   <soapenv:Header/>
   <soapenv:Body>
      <dev:authenticate>
         <dev:strUserName>username</dev:strUserName>
         <dev:strPassword>password</dev:strPassword>
      </dev:authenticate>
   </soapenv:Body>
</soapenv:Envelope>
Run Code Online (Sandbox Code Playgroud)

......有些看起来像这样:

<s11:Envelope 
 xmlns:s11='http://schemas.xmlsoap.org/soap/envelope/' 
 xmlns:ns1='http://developer.intuit.com/'>
  <s11:Header/>
  <s11:Body>
    <ns1:authenticate>
      <ns1:strUserName>username</ns1:strUserName>
      <ns1:strPassword>password</ns1:strPassword>
    </ns1:authenticate>
  </s11:Body>
</s11:Envelope>
Run Code Online (Sandbox Code Playgroud)

...或这个:

<SOAP-ENV:Envelope 
 xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
 xmlns:ns1="http://developer.intuit.com/">
   <SOAP-ENV:Header/>
   <SOAP-ENV:Body>
      <ns1:authenticate>
         <ns1:strUserName>username</ns1:strUserName>
         <ns1:strPassword>password</ns1:strPassword>
      </ns1:authenticate>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Run Code Online (Sandbox Code Playgroud)

我理解使用xpath()来选择元素,但是假设你知道要查找的命名空间.在命名空间没有任何一致性的情况下,我很难弄清楚如何正确地和编程地选择要处理的节点的内容.

命名空间在这个应用程序中完全不相关 - 我可以通过正则表达式运行原始XML来whatever:<whatever:mytag>第一个中删除吗?

Jos*_*vis 5

首先,如果您计划大量使用SOAP,您可能需要查看PHP的SOAP扩展(如果您还没有).但我从来没有用过它.

回到你的问题,你说"在我的情况下,我在SOAP请求中看到了不一致的命名空间." 准备好,因为我要打击你的想法:不,你没有.:)

在这三个例子中,两个名称空间是相同的:有http://schemas.xmlsoap.org/soap/envelope/,有http://developer.intuit.com/- 这里有什么不同的是它们的前缀.好消息是前缀并不重要.将其视为命名空间的别名.文档中使用的前缀会自动注册以在XPath中使用,但您也可以注册自己的前缀.

下面是一个如何使用文档中定义的前缀的示例(如果您已经知道它们是什么,那就很好)或者注册您自己的前缀并使用它们.

$xml = '<soapenv:Envelope 
 xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
 xmlns:dev="http://developer.intuit.com/">
   <soapenv:Header/>
   <soapenv:Body>
      <dev:authenticate>
         <dev:strUserName>username</dev:strUserName>
         <dev:strPassword>password</dev:strPassword>
      </dev:authenticate>
   </soapenv:Body>
</soapenv:Envelope>';

$Envelope = simplexml_load_string($xml);

// you can register and use your own prefixes
$Envelope->registerXPathNamespace('soap', 'http://schemas.xmlsoap.org/soap/envelope/');
$Envelope->registerXPathNamespace('auth', 'http://developer.intuit.com/');

$nodes = $Envelope->xpath('/soap:Envelope/soap:Body/auth:authenticate/auth:strUserName');
$username = (string) $nodes[0];

// or you can use the prefixes that are already defined in the document
$nodes = $Envelope->xpath('/soapenv:Envelope/soapenv:Body/dev:authenticate/dev:strPassword');
$password = (string) $nodes[0];

var_dump($username, $password);
Run Code Online (Sandbox Code Playgroud)