Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to add an xml node based on the value of a text node

I am playing around with an xml file found @ http://www.jsphylosvg.com/examples/source.php?example=2&t=xml

I would like to insert a node if the value of the node name="Espresso".

E.g. I would like to change from:

<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>

Based on the research I have done thus far I can use xpath to find the node that contains espresso (this should work, but it does not?)

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

At this point, it should be possible to use use lxml.etree.Element to make the xml node, and use insert to attach them into xml document

However, while this sounds great in theory, I am unable to get it to work.
I would really appreciate any help/suggestions

like image 722
Stylize Avatar asked Aug 13 '12 01:08

Stylize


1 Answers

Your XPath statement is not exactly right. Here's what I think you want:

>>> 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"]')

Then to append the element after the matches:

>>> 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>

EDIT:

Since your document has a namespace, you want to pass a namespace map to the XPath function and prefix the tag name with the namespace prefix, like this:

>>> nsmap = {'phylo': 'http://www.phyloxml.org'}
>>> tree.xpath('//phylo:name[text()="Espresso"]', namespaces=nsmap)
[<Element {http://www.phyloxml.org}name at 0x2c875f0>]
like image 196
jterrace Avatar answered Sep 28 '22 05:09

jterrace