使用ElementTree解析Python中的XML示例

69 投票
2 回答
160860 浏览
提问于 2025-04-15 16:19

我在找一个简单的例子,教我怎么用 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 个回答

22

如果我理解你的问题没错的话:

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 就可以了)

49

我现在在我的电脑上有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不太可能有什么明显的问题。请更新你的问题,提供任何错误信息、回溯信息,或者其他能帮助我们帮助你的内容。

撰写回答