具有许多名称空间的PHP解析XML响应 [英] PHP Parse XML response with many namespaces
问题描述
是否有一种方法可以在PHP中解析XML响应,同时考虑所有命名空间节点并将其转换为对象或数组,而无需知道所有节点名称?
Is there a way to parse through an XML response in PHP, taking into account all namespaced nodes and convert it to an object or array without knowing all the node names?
例如,将其转换为
<?xml version="1.0" encoding="ISO-8859-1"?>
<serv:message xmlns:serv="http://www.webex.com/schemas/2002/06/service"
xmlns:com="http://www.webex.com/schemas/2002/06/common"
xmlns:att="http://www.webex.com/schemas/2002/06/service/attendee">
<serv:header>
<serv:response>
<serv:result>SUCCESS</serv:result>
<serv:gsbStatus>PRIMARY</serv:gsbStatus>
</serv:response>
</serv:header>
<serv:body>
<serv:bodyContent xsi:type="att:lstMeetingAttendeeResponse"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<att:attendee>
<att:person>
<com:name>James Kirk</com:name>
<com:firstName>James</com:firstName>
<com:lastName>Kirk</com:lastName>
<com:address>
<com:addressType>PERSONAL</com:addressType>
</com:address>
<com:phones />
<com:email>Jkirk@sz.webex.com</com:email>
<com:type>VISITOR</com:type>
</att:person>
<att:contactID>28410622</att:contactID>
<att:joinStatus>INVITE</att:joinStatus>
<att:meetingKey>803754412</att:meetingKey>
</att:attendee>
</serv:bodyContent>
</serv:body>
</serv:message>
类似于:
['message' => [
'header' => [
'response' => [
'result' => 'SUCCESS',
'gsbStatus' => 'PRIMARY'
]
],
'body' => [
'bodyContent' => [
'attendee' => [
'person' => [
'name' => 'James Kirk',
'firstName' => 'James',
...
],
'contactID' => 28410622,
...
]
]
]
]
我知道使用非命名空间的节点很容易,但是我不知道从哪里开始这样的事情.
I know it's easy with non-namespaced nodes, but I don't know where to begin on something like this.
推荐答案
(请阅读@ThW的答案,为什么数组实际上并不那么重要)
(Read @ThW's answer about why an array is actually not that important to aim for)
我知道使用非命名空间的节点很容易,但是我不知道从哪里开始这样的事情.
I know it's easy with non-namespaced nodes, but I don't know where to begin on something like this.
这与命名空间节点一样容易,因为从技术上讲,它们是相同的.让我们举个简单的例子,以下脚本循环遍历文档中的所有元素,而不管名称空间如何:
It's as easy as with namespaced nodes because technically those are the same. Let's give a quick example, the following script loops over all elements in the document regardless of namespace:
$result = $xml->xpath('//*');
foreach ($result as $element) {
$depth = count($element->xpath('./ancestor::*'));
$indent = str_repeat(' ', $depth);
printf("%s %s\n", $indent, $element->getName());
}
您的情况输出为:
message
header
response
result
gsbStatus
body
bodyContent
attendee
person
name
firstName
lastName
address
addressType
phones
email
type
contactID
joinStatus
meetingKey
如您所见,您可以遍历所有元素,就好像它们根本没有任何名称空间一样.
As you can see you can iterate over all elements as if they would not have any namespace at all.
但是正如已经概述的那样,当您忽略名称空间时,您还将丢失重要的信息.例如,对于您拥有的文档,您实际上对 attendee 和 common 元素感兴趣,而 service 元素处理传输:>
But as it has been outlined, when you ignore the namespace you'll also loose important information. For example with the document you have you're actually interested in the attendee and common elements, the service elements deal with the transport:
$uriAtt = 'http://www.webex.com/schemas/2002/06/service/attendee';
$xml->registerXPathNamespace('att', $uriAtt);
$uriCom = 'http://www.webex.com/schemas/2002/06/common';
$xml->registerXPathNamespace('com', $uriCom);
$result = $xml->xpath('//att:*|//com:*');
foreach ($result as $element) {
$depth = count($element->xpath("./ancestor::*[namespace-uri(.) = '$uriAtt' or namespace-uri(.) = '$uriCom']"));
$indent = str_repeat(' ', $depth);
printf("%s %s\n", $indent, $element->getName());
}
这次的示例输出:
attendee
person
name
firstName
lastName
address
addressType
phones
email
type
contactID
joinStatus
meetingKey
那么为什么要删除所有名称空间?它们可以帮助您获取您感兴趣的元素.您也可以动态地进行
So why drop all the namespaces? They help you to obtain the elements you're interested in. You can also do it dynamically
这篇关于具有许多名称空间的PHP解析XML响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!