使用ElementTree解析Python中的XML示例
我在找一个简单的例子,教我怎么用 Python 的 Element Tree 来解析 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 中命名空间的更多信息,请查看 这个页面。
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
就可以了)
我现在在我的电脑上有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不太可能有什么明显的问题。请更新你的问题,提供任何错误信息、回溯信息,或者其他能帮助我们帮助你的内容。