使用Python lxml无法访问XML孙标签,求解决方案
问题分析与解决思路
你遇到的核心问题是XML命名空间的处理不当——你的XML里既有默认命名空间(TrainingCenterDatabase/v2),又有ActivityExtension/v2这个子命名空间,所有元素的查找都必须带上对应的命名空间才能定位到,这也是为什么你的CSV只有表头的原因:根本没找到任何匹配的节点。
我来帮你一步步修正代码:
1. 简化XML解析流程
你不需要先parse再转成字符串,再用fromstring解析,直接用parse()后的getroot()拿到根节点就行,多余的解析步骤不仅没用,还可能引入额外问题。
2. 正确使用命名空间查找节点
- 默认命名空间下的
Trackpoint、Extensions需要用tcx前缀绑定的命名空间定位 TPX以及它下面的Speed、Watts属于ext前缀绑定的命名空间,查找时必须指定这个命名空间
修正后的完整代码
import lxml.etree as et import csv # 定义命名空间字典,用前缀简化写法 NS = {'tcx': 'http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2', 'ext': 'http://www.garmin.com/xmlschemas/ActivityExtension/v2'} # 直接解析XML文件并获取根节点 tree = et.parse('sample.tcx', parser=et.XMLParser(remove_comments=True)) root = tree.getroot() header = ('Speed', 'Watts') with open('output1.csv', 'w', newline='') as g: writer = csv.writer(g) writer.writerow(header) # 用XPath配合命名空间前缀,精准定位所有TPX节点 for tpx in root.xpath('//tcx:Trackpoint/tcx:Extensions/ext:TPX', namespaces=NS): # 子节点Speed和Watts同样属于ext命名空间,必须指定前缀查找 speed = tpx.find('ext:Speed', namespaces=NS).text watts = tpx.find('ext:Watts', namespaces=NS).text writer.writerow([speed, watts])
关键调整点说明
- 用命名空间字典绑定前缀,让XPath写法更简洁,避免重复写冗长的命名空间URI
- 使用
xpath()代替iter(),配合前缀精准定位层级节点://tcx:Trackpoint/tcx:Extensions/ext:TPX明确指定了每个层级元素所属的命名空间 - 子节点
Speed和Watts同样属于ext命名空间,所以find()时必须带上namespaces=NS和前缀ext:
这样运行后,就能正确提取到孙标签里的Speed和Watts值,写入CSV文件了。
内容的提问来源于stack exchange,提问作者vanoccupanther
相关产品推荐
相关产品推荐

