使用 ElementTree 示例在 Python 中解析 XML

Posted

技术标签:

【中文标题】使用 ElementTree 示例在 Python 中解析 XML【英文标题】:Parsing XML in Python using ElementTree example 【发布时间】:2010-12-19 16:17:15 【问题描述】:

我很难找到一个好的基本示例,说明如何使用元素树在 python 中解析 XML。据我所知,这似乎是用于解析 XML 的最简单的库。这是我正在使用的 XML 示例:

<timeSeriesResponse>
    <queryInfo>
        <locationParam>01474500</locationParam>
        <variableParam>99988</variableParam>
        <timeParam>
            <beginDateTime>2009-09-24T15:15:55.271</beginDateTime>
            <endDateTime>2009-11-23T15:15:55.271</endDateTime>
        </timeParam>
     </queryInfo>
     <timeSeries name="NWIS Time Series Instantaneous Values">
         <values count="2876">
            <value dateTime="2009-09-24T15:30:00.000-04:00" qualifiers="P">550</value>
            <value dateTime="2009-09-24T16:00:00.000-04:00" qualifiers="P">419</value>
            <value dateTime="2009-09-24T16:30:00.000-04:00" qualifiers="P">370</value>
            .....
         </values>
     </timeSeries>
</timeSeriesResponse>

我能够使用硬编码的方法做我需要的事情。但我需要我的代码更有活力。这是有效的:

tree = ET.parse(sample.xml)
doc = tree.getroot()

timeseries =  doc[1]
values = timeseries[2]

print child.attrib['dateTime'], child.text
#prints 2009-09-24T15:30:00.000-04:00, 550

这是我尝试过的几件事,但都没有奏效,报告说他们找不到 timeSeries(或我尝试过的任何其他东西):

tree = ET.parse(sample.xml)
tree.find('timeSeries')

tree = ET.parse(sample.xml)
doc = tree.getroot()
doc.find('timeSeries')

基本上,我想加载xml文件,搜索timeSeries标签,遍历value标签,返回dateTime和标签本身的值;我在上面的例子中所做的一切,但没有对我感兴趣的 xml 部分进行硬编码。谁能给我一些例子,或者给我一些关于如何解决这个问题的建议?


感谢所有帮助。使用以下两个建议都适用于我提供的示例文件,但是,它们不适用于完整文件。这是我在使用 Ed Carrel 的方法时从真实文件中得到的错误:

 (<type 'exceptions.AttributeError'>, AttributeError("'NoneType' object has no attribute 'attrib'",), <traceback object at 0x011EFB70>)

我认为它不喜欢真实文件中的某些内容,因此我逐步删除了某些内容,直到它起作用为止。以下是我更改的行:

originally: <timeSeriesResponse xsi:schemaLocation="a URL I removed" xmlns="a URL I removed" xmlns:xsi="a URL I removed">
 changed to: <timeSeriesResponse>

 originally:  <sourceInfo xsi:type="SiteInfoType">
 changed to: <sourceInfo>

 originally: <geogLocation xsi:type="LatLonPointType" srs="EPSG:4326">
 changed to: <geogLocation>

删除具有 'xsi:...' 的属性解决了这个问题。 'xsi:...' 不是有效的 XML 吗?我很难以编程方式删除这些。有什么建议的解决方法吗?

这是完整的 XML 文件:http://www.sendspace.com/file/lofcpt


当我最初问这个问题时,我不知道 XML 中的名称空间。现在我知道发生了什么,我不必删除作为命名空间声明的“xsi”属性。我只是将它们包含在我的 xpath 搜索中。有关 lxml 中命名空间的更多信息,请参阅 this page。

【问题讨论】:

我可以建议您查看lxml 提供的etree 模块吗?我最近发现了它,并发现它比 ElementTree 优越得多。它是作为完全模拟 ElementTree 的替代品编写的。 我最终选择了 lxml,因为它更容易使用,但我仍然遇到上述问题。作为解决方法,我事先扫描 xml 文件并删除所有“xsi:type”实例。以下答案中概述的方法可以正常工作。 【参考方案1】:

所以现在我的盒子上有 ElementTree 1.2.6,并针对您发布的 XML 块运行以下代码:

import elementtree.ElementTree as ET

tree = ET.parse("test.xml")
doc = tree.getroot()
thingy = doc.find('timeSeries')

print thingy.attrib

并得到以下回复:

'name': 'NWIS Time Series Instantaneous Values'

它似乎找到了 timeSeries 元素,而无需使用数字索引。

现在有用的是当你说“它不起作用”时知道你的意思。由于它在给定相同输入的情况下对我有用,因此 ElementTree 不太可能以某种明显的方式被破坏。使用任何错误消息、回溯或您可以提供的任何内容来更新您的问题以帮助我们帮助您。

【讨论】:

对于新的python版本,导入已更改为:import xml.etree.ElementTree as ET @Louis:“新的 python 版本”是什么意思? @Monica Heddneck : 因为这条评论已经有六年的历史了,我应该说每条 python 都在 2.3 以上...【参考方案2】:

如果我正确理解您的问题:

for elem in doc.findall('timeSeries/values/value'):
    print elem.get('dateTime'), elem.text

或者,如果您愿意(如果timeSeries/values 只出现一次:

values = doc.find('timeSeries/values')
for value in values:
    print value.get('dateTime'), elem.text

findall() 方法返回所有匹配元素的列表,而find() 只返回第一个匹配元素。第一个示例循环遍历所有找到的元素,第二个示例循环遍历 values 元素的子元素,在这种情况下导致相同的结果。

我不明白找不到timeSeries 的问题出在哪里。也许您只是忘记了getroot() 电话? (请注意,您实际上并不需要它,因为您也可以从元素树本身工作,如果您将路径表达式更改为例如 /timeSeriesResponse/timeSeries/values//timeSeries/values

【讨论】:

效果很好。我将它与from lxml import etree 模块一起使用。 doc = etree.parse('test.xml')

以上是关于使用 ElementTree 示例在 Python 中解析 XML的主要内容,如果未能解决你的问题,请参考以下文章

Python实现XML的操作

python的XML处理模块ElementTree

Python:XPath 在 ElementTree 中不可用

在 Python 中通过 ElementTree 解析 xml 时如何保留命名空间

使用Python和ElementTree解析XML

如何使用 ElementTree python 在 xml 解析器中处理 CDATA?