【问题标题】:Adding child element to XML in python在python中将子元素添加到XML
【发布时间】:2018-04-28 11:53:29
【问题描述】:

我在 XML 文件中有一个元素:

<condition>
  <comparison compare="and">
    <operand idref="XXX" type="boolean" />
  </comparison>
</condition>

我需要添加另外两个子元素(child1 和 child2),例如:

<condition>
  <child1 compare='and'>
    <child2 idref='False' type='int' /> 
    <comparison compare="and">
      <operand idref="XXX" type="boolean" />
    </comparison>
  </child1>
</condition>

我继续使用 lxml:

from lxml import etree
tree = etree.parse(xml_file)
condition_elem = tree.find("<path for the condition block in the xml>")
etree.SubElement(condition_elem, 'child1')
tree.write( 'newXML.xml', encoding='utf-8', xml_declaration=True)

这只是将元素 child1 添加为元素条件的子元素,如下所示,不满足我的要求:

<condition>
  <child1></child1>
  <comparison compare="and">
    <operand idref="XXX" type="boolean" />
  </comparison>
</condition>

有什么想法吗?谢谢

【问题讨论】:

    标签: python xml lxml elementtree xml.etree


    【解决方案1】:

    在它的 etree 子模块上使用 lxml 的 objectify 子模块,我会从根中删除比较元素,将 child1 元素添加到其中,然后将内容比较重新添加到其中:

    from lxml import objectify
    
    tree = objectify.parse(xml_file)
    condition = tree.getroot()
    comparison = condition.comparison
    
    M = objectify.ElementMaker(annotate=False)
    child1 = M("child1", {'compare': 'and'})
    child2 = M("child2", {'idref': 'False', 'type': 'int'})
    
    condition.remove(comparison)
    condition.child1 = child1
    condition.child2 = child2
    condition.child1.comparison = comparison
    

    ElementMaker 是一个易于使用的工具,用于创建新的 xml 元素。我首先是它的一个实例(M),它没有对 xml 进行注释(用属性乱扔它),然后使用该实例来创建您要求的孩子。其余的我认为是不言自明的。

    【讨论】:

    • 关于标签名称的一句话,因为 objectify 对这些有点好笑。当我创建 child1 和 child2 元素时,它是确定标签名称的第一个参数,即引用的“child1”/“child2”。为清楚起见,我只是对 python 变量使用相同的名称。但是,当我将这些元素添加到“条件”元素时,它们的标签名称会更改为属性的名称。如果我使用了“condition.evil_spawn = child1”,则条件子项的标签名称将是“evil_spawn”,而不是子项。由于我们在这里仍然使用“child1”,所以没有任何变化。
    • 如果我在同一关卡中有多个 元素怎么办?
    • comparison = condition.comparison 以标签名称为“比较”的第一个元素为目标。要获取comparison 元素的列表,请执行condition.comparison[:]