我正在尝试使用Element树从XML中定位感兴趣的元素,并从XML中删除整个组(即父组)。
import xml.etree.ElementTree as ET
from lxml import etree
copasiML_str= IA.read_copasiML_as_string(model_file) # Reads XML as string
copasiML=ET.fromstring(copasiML_str) # parse XML to etree
for i in copasiML.findall(".//*[@name='ObjectCN']"): # locate element
if '[v18]' in i.attrib['value']: #search for 'v18'
if 'Parameter=V' in i.attrib['value']: #search for 'Parameter=V'
print i.attrib['value'] #Element identified
parent = i.getparent() #gets the parent of identified
copasiML.remove(parent) # This does not work
此代码标识元素并获取我要删除的元素的父元素。然后,当我尝试删除元素时,它会给我一个错误:
ValueError: Element is not a child of this node.
有问题的XML相当复杂。这是一个片段:
<ParameterGroup name="FitItem">
<ParameterGroup name="Affected Cross Validation Experiments">
</ParameterGroup>
<ParameterGroup name="Affected Experiments">
<Parameter name="Experiment Key" type="key" value="Experiment_1"/>
<Parameter name="Experiment Key" type="key" value="Experiment_2"/>
<Parameter name="Experiment Key" type="key" value="Experiment_4"/>
</ParameterGroup>
<Parameter name="LowerBound" type="cn" value="1e-06"/>
<Parameter name="ObjectCN" type="cn" value="CN=Root,Model=NoName,Vector=Reactions[V18],ParameterGroup=Parameters,Parameter=V,Reference=Value"/>
<Parameter name="StartValue" type="float" value="0.1852208634119804"/>
<Parameter name="UpperBound" type="cn" value="100"/>
</ParameterGroup>
有许多'FitItem'参数组。我正试图找到一个'[V18]'和'Parameter = V'并删除整个FitItem。有人会知道怎么做吗?
由于
答案 0 :(得分:1)
如果发布的XML只是更大的XML的一部分,并且<ParameterGroup name="FitItem">
实际上不是根元素,那么您应该能够删除parent
变量引用的元素&#39;父母(不要感到困惑),如下:
......
parent = i.getparent()
parent.getparent().remove(parent)
否则,您无法删除parent
,因为它引用了根元素,而XML文档只需要一个根元素就可以保留为XML格式。
这是演示的一个工作示例:
from lxml import etree
xml = '''<root>
<ParameterGroup name="FitItem">
<ParameterGroup name="Affected Cross Validation Experiments">
</ParameterGroup>
<ParameterGroup name="Affected Experiments">
<Parameter name="Experiment Key" type="key" value="Experiment_1"/>
<Parameter name="Experiment Key" type="key" value="Experiment_2"/>
<Parameter name="Experiment Key" type="key" value="Experiment_4"/>
</ParameterGroup>
<Parameter name="LowerBound" type="cn" value="1e-06"/>
<Parameter name="ObjectCN" type="cn" value="CN=Root,Model=NoName,Vector=Reactions[V18],ParameterGroup=Parameters,Parameter=V,Reference=Value"/>
<Parameter name="StartValue" type="float" value="0.1852208634119804"/>
<Parameter name="UpperBound" type="cn" value="100"/>
</ParameterGroup>
</root>'''
copasiML=etree.fromstring(xml)
query = "//*[@name='ObjectCN'][contains(@value,'[V18]')][contains(@value,'Parameter=V')]"
for i in copasiML.xpath(query):
parent = i.getparent()
parent.getparent().remove(parent)
print etree.tostring(copasiML)
输出
<root>
</root>
答案 1 :(得分:1)
一旦我学会BeautifulSoup,我就再也不会使用etree了。
注意:
find(lamda)
,find(args..)
,因为您有很多规则定位FitItem,而您的查找父逻辑非常简单。 以下是代码:
from bs4 import BeautifulSoup
myString = """
<ParameterGroup name="copasiML">
<ParameterGroup name="FitItem">
<ParameterGroup name="Affected Cross Validation Experiments"></ParameterGroup>
<ParameterGroup name="Affected Experiments">
<Parameter name="Experiment Key" type="key" value="Experiment_1"/>
<Parameter name="Experiment Key" type="key" value="Experiment_2"/>
<Parameter name="Experiment Key" type="key" value="Experiment_4"/>
</ParameterGroup>
<Parameter name="LowerBound" type="cn" value="1e-06"/>
<Parameter name="ObjectCN" type="cn" value="CN=Root,Model=NoName,Vector=Reactions[V18],ParameterGroup=Parameters,Parameter=V,Reference=Value"/>
<Parameter name="StartValue" type="float" value="0.1852208634119804"/>
<Parameter name="UpperBound" type="cn" value="100"/>
</ParameterGroup>
<ParameterGroup name="FitItem">Datafireball</ParameterGroup>
</ParameterGroup>
"""
soup = BeautifulSoup(myString, "xml")
def myfunc(e):
try:
if (e['name'] == 'ObjectCN') and (e.name == 'Parameter') and ('V18' in e['value']):
return True
else:
return False
except:
return False
target = soup.find(lambda x: myfunc(x))
parent = target.find_parent('ParameterGroup', {'name':'FitItem'})
parent.decompose()
print soup.prettify()
这是输出:
<?xml version="1.0" encoding="utf-8"?>
<ParameterGroup name="copasiML">
<ParameterGroup name="FitItem">
Datafireball
</ParameterGroup>
</ParameterGroup>