PHP的SimpleXML:在SOAP处理未知的命名空间请求
有一个tonofexistingquestions关于PHP的SimpleXML和使用命名空间的处理XML。所有的我看了都取得了基本假设的问题:提前命名空间会是什么代码知道要包含在传入的SOAP请求。就我而言,我在SOAP请求中看到了不一致的名称空间。PHP的SimpleXML:在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()选择ELE发言:,但假设你知道如何寻找的命名空间中,没有任何一致性的命名空间,我有一个很难搞清楚如何正确,程序选择处理节点的内容。
命名空间在这个应用程序中是完全不相关的 - 我可以通过正则表达式运行原始XML以便首先从<whatever:mytag>
中删除whatever:
?
首先,如果你打算使用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);
有几个有用的SimpleXML元方法中的XPath查询方法时可以帮助您确定并使用正确的命名空间。前两个是getNamespaces和getDocNamespaces。使用getNamespaces将返回所有文档中使用的命名空间(指定递归参数),而getDocNamespaces将返回文档中声明的所有命名空间。
一旦你有可用的命名空间的数组,你可以使用registerXPathNamespace注册每个命名空间到你要使用XPath方法simplexml_element。
我是一个新用户,所以我不能发布PHP的文档中的链接到其他的方法。
我*想*我明白你的意思,但肯定会有助于看到一个例子。假设我想要一个$ var包含一个用于验证的SimpleXMLElement,并带有两个子项:strUserName和strPassword。我的目标是能够将通用化(意味着元素名称中没有名称空间)对象传递给仅知道寻找$ var-> children() - > strUserName的处理程序。 – beporter 2011-01-26 17:33:19
是的!我将前缀理解为命名空间的快捷方式。具有讽刺意味的是,我实际上是在尝试过自己的解决方案之前,无法让xpath识别我定义的备用前缀。我一定是做错了事。我显然还没有完全理解Xpath。原谅新手跟进问题(在这一点上应该不会令人惊讶),但是如果我不一定知道紧接着身体的下一个标记是什么,我仍然可以通过通配符选择它,或者一个使用'/ soap:Envelope/child :: soap:Body'的轴? – beporter 2011-01-27 14:44:29