有关于PHP的simpleXML和使用命名空间处理XML的ton of existing questions。我所看到的所有问题都提出了一个基本假设:代码事先知道将在传入的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>
......有些看起来像这样:
<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>
......或者这个:
<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>
我理解使用xpath()来选择元素,但是假设你知道要查找的命名空间。在命名空间没有任何一致性的情况下,我很难弄清楚如何正确和以编程方式选择内容要处理的节点。
命名空间在此应用程序中完全无关紧要 - 我是否可以通过正则表达式运行原始XML以首先从whatever:
删除<whatever:mytag>
?
答案 0 :(得分:5)
首先,如果您计划大量使用SOAP,如果您还没有,可能需要查看PHP's SOAP extension。但我从未使用它。
回到你的问题,你说“在我的情况下,我在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);
答案 1 :(得分:1)
有一些有用的simplexml元素方法可以帮助您在使用xpath方法查询时确定并使用正确的命名空间。前两个是getNamespaces和getDocNamespaces。 getNamespaces将返回文档中使用的所有命名空间(指定递归参数),而getDocNamespaces将返回文档声明的所有命名空间。
一旦有了可用的命名空间数组,就可以使用registerXPathNamespace将每个命名空间注册到要使用xpath方法的simplexml_element。
我是新用户,因此无法将链接发布到php文档中的其他方法。