使用 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:XPath 在 ElementTree 中不可用