具有许多名称空间的PHP解析XML响应 [英] PHP Parse XML response with many namespaces

查看:70
本文介绍了具有许多名称空间的PHP解析XML响应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否有一种方法可以在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆