在Python中更新XML属性值
在下面的XML中,我想解析它,并把所有年龄大于21的地方的“alcohol”值更新为“yes”。我遇到的问题是这个值被埋在其他节点里面。有人能帮我理解该怎么处理吗?
这是XML的内容..
<root xmlns="XYZ" usingPalette="">
<grandParent hostName="XYZ">
<parent>
<child name="JohnsDad">
<grandChildren name="John" sex="male" age="22" alcohol="no"/>
</child>
<child name="PaulasDad">
<grandChildren name="Paula" sex="female" age="15" alcoho="no"/>
</child>
</parent>
</grandParent>
</root>
我尝试过使用这个文档中的查找所有和查找方法(http://pymotw.com/2/xml/etree/ElementTree/parse.html),但是没有找到。例如,下面的代码没有返回任何结果
for node in tree.findall('.//grandParent'):
print node
1 个回答
2
import xml.etree.ElementTree as ET
tree = ET.parse('data')
for node in tree.getiterator():
if int(node.attrib.get('age', 0)) > 21:
node.attrib['alcohol'] = 'yes'
root = tree.getroot()
ET.register_namespace("", "XYZ")
print(ET.tostring(root))
产生
<root xmlns="XYZ" usingPalette="">
<grandParent hostName="XYZ">
<parent>
<child name="JohnsDad">
<grandChildren age="22" alcohol="yes" name="John" sex="male" />
</child>
<child name="PaulasDad">
<grandChildren age="15" alcoho="no" name="Paula" sex="female" />
</child>
</parent>
</grandParent>
</root>
顺便提一下,由于XML使用了“XYZ”这个命名空间,你必须在你的XPath中指定这个命名空间:
for node in tree.findall('.//{XYZ}grandParent'):
print node
这将返回grandParent元素,但因为你想检查所有的子节点,我觉得使用getiterator
会更简单一些。
如果你想在使用xml.etree.ElementTree
时保留注释,你可以使用Fredrik Lundh在这里展示的自定义解析器:
import xml.etree.ElementTree as ET
class PIParser(ET.XMLTreeBuilder):
"""
http://effbot.org/zone/element-pi.htm
"""
def __init__(self):
ET.XMLTreeBuilder.__init__(self)
# assumes ElementTree 1.2.X
self._parser.CommentHandler = self.handle_comment
self._parser.ProcessingInstructionHandler = self.handle_pi
self._target.start("document", {})
def close(self):
self._target.end("document")
return ET.XMLTreeBuilder.close(self)
def handle_comment(self, data):
self._target.start(ET.Comment, {})
self._target.data(data)
self._target.end(ET.Comment)
def handle_pi(self, target, data):
self._target.start(ET.PI, {})
self._target.data(target + " " + data)
self._target.end(ET.PI)
tree = ET.parse('data', PIParser())
注意,如果你安装了lxml,你可以改用:
import lxml.etree as ET
parser = ET.XMLParser(remove_comments=False)
tree = etree.parse('data', parser=parser)