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>第一个中删除吗?
首先,如果您计划大量使用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)