如何根据文本节点的值添加XML节点

5

我是一个有用的助手,可以帮您进行翻译。

我正在尝试处理一个XML文件,它位于http://www.jsphylosvg.com/examples/source.php?example=2&t=xml

如果节点name="Espresso"的值,我想插入一个节点。

例如,我想从以下内容进行更改:

<clade>
<name>Espresso</name>
<branch_length>2.0</branch_length>
</clade>

to:

<clade>
<name>Espresso</name>
<url>www.espresso.com</url>
<branch_length>2.0</branch_length>
</clade>

根据我目前的研究,我可以使用 xpath 找到包含 espresso 的节点 (这应该行得通,但为什么不行呢?)

import re, sys
import lxml.etree
f = open("test.xml", "r")
data = f.read()
tree = lxml.etree.XML(data)
if tree.xpath('//name/text()="Espresso"'):
    insert new child here

目前为止,可以使用lxml.etree.Element创建XML节点,并使用insert方法将它们附加到XML文档中。

但是,在理论上听起来很好的同时,我无法使其正常工作。
如果有任何帮助或建议,我会非常感激。

1个回答

5

您的XPath语句并不完全正确。以下是我认为您想要的:

>>> DOC = """<clade>
... <name>Espresso</name>
... <branch_length>2.0</branch_length>
... </clade>"""
>>> 
>>> import lxml.etree
>>> tree = lxml.etree.XML(DOC)
>>> matches = tree.xpath('//name[text()="Espresso"]')

然后在匹配项后追加元素:

>>> for e in matches:
...    sibling = lxml.etree.Element("url")
...    sibling.text = "www.espresso.com"
...    e.addnext(sibling)

>>> print lxml.etree.tostring(tree)
<clade>
<name>Espresso</name><url>www.espresso.com</url>
<branch_length>2.0</branch_length>
</clade>

编辑:

由于您的文档具有命名空间,因此您需要向XPath函数传递命名空间映射,并使用命名空间前缀为标记名称加上前缀,如下所示:

>>> nsmap = {'phylo': 'http://www.phyloxml.org'}
>>> tree.xpath('//phylo:name[text()="Espresso"]', namespaces=nsmap)
[<Element {http://www.phyloxml.org}name at 0x2c875f0>]

谢谢你的示例DOC,代码运行得非常好。然而,使用实际文件时似乎不起作用。 - Stylize
@Stylize - 可能失败是因为实际文件有默认命名空间。 - Daniel Haley
2
@Stylize 添加了有关命名空间的信息。 - jterrace
@jterrace,再次感谢!我已经接受了你的答案。你能给我指一些关于命名空间的背景阅读材料吗?在xml中拥有命名空间的好处是什么? - Stylize
请阅读lxml命名空间部分。如果需要一些背景知识,可以参考维基百科页面 - jterrace

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接