使用lxml修改XML中Watts标签内容及getroot()作用咨询
嘿,我来帮你搞定这两个问题!
问题出在XML命名空间上!你看你的XML里,Watts标签嵌套在TPX里面,而TPX有自己的命名空间:xmlns="http://www.garmin.com/xmlschemas/ActivityExtension/v2"。在lxml中,带有命名空间的标签,它的tag属性不是单纯的"Watts",而是包含命名空间的完整名称,格式是"{命名空间URL}标签名",也就是"{http://www.garmin.com/xmlschemas/ActivityExtension/v2}Watts"。所以你原来的判断watt.tag == "Watts"永远不会成立,自然不会修改任何内容。
有几种解决方法:
方法1:直接匹配带命名空间的标签名
修改你的循环判断,直接对比完整的带命名空间的tag:
from lxml import etree tree = etree.parse("cycling.xml") root = tree.getroot() # 定义Watts标签的完整命名空间名称 WATTS_TAG = "{http://www.garmin.com/xmlschemas/ActivityExtension/v2}Watts" for elem in root.iter(): if elem.tag == WATTS_TAG: elem.text = "strong" tree.write("output.xml")
方法2:使用XPath(更简洁推荐)
利用XPath的命名空间支持,直接定位所有Watts标签:
from lxml import etree tree = etree.parse("cycling.xml") # 定义命名空间映射,给命名空间起个短别名 ns_map = { "tcd": "http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2", "ae": "http://www.garmin.com/xmlschemas/ActivityExtension/v2" } # 使用XPath选择所有ae:Watts标签 for watts in tree.xpath("//ae:Watts", namespaces=ns_map): watts.text = "strong" tree.write("output.xml")
这种方法更清晰,尤其是当XML有多个命名空间的时候,可读性更好。
root = tree.getroot()的作用是什么? tree = etree.parse("cycling.xml")会把整个XML文件解析成一个ElementTree对象,这个对象代表了整个XML文档的结构,但它本身不是XML元素。而tree.getroot()的作用就是获取这个XML文档的根元素(也就是你XML里的<TrainingCenterDatabase>标签),之后你通过root.iter()遍历的所有元素,都是这个根元素的子元素、孙元素等。简单来说:
tree是整个文档的容器,包含了XML的所有信息和解析后的结构root是文档的入口点,你所有的元素遍历、修改操作都要从根元素开始发起
如果没有获取根元素,你没法直接对XML的内容进行遍历和修改,因为ElementTree对象本身不提供直接遍历子元素的方法。
内容的提问来源于stack exchange,提问作者Doug Smith

