XML一直在抛弃曲线球。我很难找到一本我能理解的手册。所以我为过去几天的所有问题道歉。
无论如何,我有以下XML:
<clade>
<clade>
<branch_length>0.5</branch_length>
<clade>
<name>MnPV1</name>
<annotation>
<desc>Iotapapillomavirus 1</desc></annotation><chart><group>Iota</group></chart><branch_length>1.0</branch_length>
</clade>
<clade>
我想将其更改为:
<clade>
<clade>
<branch_length>0.5</branch_length>
<clade>
<name bgstyle="green">MnPV1</name>
<annotation><desc>Iotapapillomavirus 1</desc><uri>http://pave.niaid.nih.gov/#fetch?id=MnPV1REF&format=Locus%20view&hasStructure=none</uri></annotation><chart><group>Iota</group></chart><branch_length>1.0</branch_length>
</clade>
<clade>
所以我想改变:
<name>MnPV1</name>
为:
<name bgstyle="green">MnPV1</name>
问题是,我正在寻找是否:
tree.xpath('//phylo:group[text()="Iota"]
如果是的话我想得到“组”节点的“叔叔”,这样我就可以编辑“名字”节点
这是我到目前为止所提出的:
tree = lxml.etree.XML(data)
nsmap = {'phylo': 'http://www.phyloxml.org'}
matches = tree.xpath('//phylo:group[text()="Iota"]', namespaces=nsmap)
for e in matches:
uncle=e.getparent().getsibling() #however, getsibling() does not exist...
我将不胜感激任何帮助(和/或lxml for dummies的建议)。
答案 0 :(得分:5)
这个怎么样?
>>> data = r'''<clade>
... <name>MnPV1</name>
... <annotation>
... <desc>Iotapapillomavirus 1</desc>
... </annotation>
... <chart>
... <group>Iota</group>
... </chart>
... <branch_length>1.0</branch_length>
... </clade>'''
...
>>> tree = lxml.etree.XML(data)
>>> for name in tree.xpath('//group[text()="Iota"]/../preceding-sibling::name'):
... name.attrib['bgstyle'] = 'green'
...
>>> print lxml.etree.tostring(tree, pretty_print=True)
<clade>
<name bgstyle="green">MnPV1</name>
<annotation>
<desc>Iotapapillomavirus 1</desc>
</annotation>
<chart>
<group>Iota</group>
</chart>
<branch_length>1.0</branch_length>
</clade>
>>>
诀窍是使用XML工具(例如,XPath和XSLT)来操作XML文档。 w3schools sites是非常好的起点。 XPath本身就相当强大,一旦掌握了它就很容易阅读。但是,使用XSLT可以最好地解决此类问题。如果您要操作一堆XML,请自己做一件大事,并购买Oxygen XML editor或类似内容的副本。
如果您正在寻找使用较少XPath和更多Python的内容,请使用getparent
,然后调用getprevious
。我不确定支持getparent
和getprevious
的支持程度如何,但它们已记录在案并且可以正常工作。
答案 1 :(得分:2)
以下是一个简单的XSLT解决方案:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="clade[chart/group='Iota']/name">
<name bgstyle="green"><xsl:apply-templates/></name>
</xsl:template>
</xsl:stylesheet>
在提供的XML文档上应用此转换时:
<clade>
<clade>
<branch_length>0.5</branch_length>
<clade>
<name>MnPV1</name>
<annotation>
<desc>Iotapapillomavirus 1</desc>
</annotation>
<chart>
<group>Iota</group>
</chart>
<branch_length>1.0</branch_length>
</clade>
</clade>
</clade>
产生了想要的正确结果:
<clade>
<clade>
<branch_length>0.5</branch_length>
<clade>
<name bgstyle="green">MnPV1</name>
<annotation>
<desc>Iotapapillomavirus 1</desc>
</annotation>
<chart>
<group>Iota</group>
</chart>
<branch_length>1.0</branch_length>
</clade>
</clade>
</clade>
说明:
使用和覆盖 identity rule ,它按“原样”复制每个节点(选择执行该节点)。
匹配所需name
元素的简单覆盖模板,并将其替换为具有所需新属性的同名元素。