在Python中遍历没有命名空间的XML树

时间:2018-01-21 21:36:18

标签: python xml xpath

我正在解析一个大的XML文件,它基本上包含一个表。 XML中的节点始终没有名称。嵌套在几个标签内的基本上是一个类似HTML的表,<TD>包含行(<TR>)标签内的原始(数字)数据。现在,在我可以迭代到表之前,有一大堆我不感兴趣的元数据标签。例如:

<?xml version="1.0" ?>
<soap:Envelope xmlns:soap="--ommitted--" xmlns:xsi="--ommitted--">
    <soap:Body>
        <FetchReportResponse xmlns="URL1">
            <FetchReportResult xmlns="URL2">
                <REPORT>
                    <TITLE>CROSS VISITING REPORT</TITLE>
                    <SUBTITLE/>
                    <SUMMARY>
                        <GEOGRAPHY>--ommitted--</GEOGRAPHY>
                        <LOCATION>--ommitted--</LOCATION>
                        <TIMEPERIOD>--ommitted--</TIMEPERIOD>
                        <TARGET>--ommitted--</TARGET>
                        <MEDIA>--ommitted--</MEDIA>
                        <DATE>--ommitted--</DATE>
                        <USER>--ommitted--</USER>
                    </SUMMARY>
                    <TABLE>
                        <THEAD>
                            <TR>
                              <TH>--ommitted--</TH>
                              <TD>--ommitted--</TD>
                              <TD>--ommitted--</TD>
                              <TD>--ommitted--</TD>
                              <TD>--ommitted--</TD>
                              <TD>--ommitted--</TD>
                              <TD>--ommitted--</TD>

我是XML解析的新手,所以我跟随this。我有以下代码来读取和XML文件并创建一个ElementTree对象。

import xml.etree.ElementTree as ET

tree = ET.parse('./../filename.xml')
print(root.find("./"))

这可以理解地打印出以下内容:

<Element '{http://schemas.xmlsoap.org/soap/envelope/}Envelope' at 0x00000230CAC23318>

但是,当我尝试使用XPath约定从此处遍历它时,我无法做到。例如,

print(root.find("./Body"))

打印None,即使<Body>明确嵌套在<Envelope>内。

编辑:按照Mark Tolonen的回答,我能够获得Body标签,但我该如何超越呢?更具体地说,我想要达到<TABLE>标记。

2 个答案:

答案 0 :(得分:1)

您需要完全限定名称,因为它是soap:Body,您希望使用xmlns:soap值限定正文,(从您的信封示例中暗示)是:

print(root.find("./{http://schemas.xmlsoap.org/soap/envelope/}Body"))

答案 1 :(得分:1)

除了XPath部分之外,您还需要关注文档的<{3}} ,因为您的XML包含各种名称空间,包含和不包含前缀(后者称为默认值)命名空间)。请注意,TABLE元素使用默认命名空间从最近的祖先继承命名空间:FetchReportResult。因此,要查找TABLE,您需要使用默认命名空间URI "URL2",使用大括号语法或使用前缀-URI字典:

ns = { "u2": "URL2" }
tables = root.findall(".//u2:TABLE", ns)