首页 > 解决方案 > 删除 XML 中的容器

问题描述

这是我的输入文件。故意留下标题,因为我认为它们与问题无关。我没有粘贴整个文件,因为它很大。我只添加了两个容器:

  <ECUC-CONTAINER-VALUE>
     <SHORT-NAME>ABC</SHORT-NAME>
     <DEFINITION-REF DEST="ECUC-PARAM-CONF-CONTAINER-DEF">/AUTOSAR_CAN/EcucModuleDefs/CanConfigSet/CanHardwareObject</DEFINITION-REF>
     <PARAMETER-VALUES>
       <ECUC-NUMERICAL-PARAM-VALUES>
         <DEFINITION-REF DEST="ECUC-INTEGER-PARAM-DEF">/AUTOSAR_CAN/EcucModuleDefs/CanConfigSet/CanHardwareObject/CANIdValue</DEFINITION-REF>
          <VALUE>1053</VALUE>
       </ECUC-NUMERICAL-PARAM-VALUES>
       <ECUC-TEXTUAL-PARAM-VALUES>
       <DEFINITION-REF DEST="ECUC-ENUMERATION-PARAM-DEF">/AUTOSAR_CAN/EcucModuleDefs/CanConfigSet/CanHardwareObject/CANHandleType</DEFINITION-REF>
           <VALUE>TRUE</VALUE>
        </ECUC-TEXTUAL-PARAM-VALUES>
      </PARAMETER-VALUES>        
<ECUC-CONTAINER-VALUE>

    <ECUC-CONTAINER-VALUE>
     <SHORT-NAME>ABC</SHORT-NAME>
     <DEFINITION-REF DEST="ECUC-PARAM-CONF-CONTAINER-DEF">/AUTOSAR_CAN/EcucModuleDefs/CanConfigSet/CanHardwareObject</DEFINITION-REF>
     <PARAMETER-VALUES>
       <ECUC-NUMERICAL-PARAM-VALUES>
         <DEFINITION-REF DEST="ECUC-INTEGER-PARAM-DEF">/AUTOSAR_CAN/EcucModuleDefs/CanConfigSet/CanHardwareObject/CANIdValue</DEFINITION-REF>
          <VALUE>1054</VALUE>
       </ECUC-NUMERICAL-PARAM-VALUES>
       <ECUC-TEXTUAL-PARAM-VALUES>
       <DEFINITION-REF DEST="ECUC-ENUMERATION-PARAM-DEF">/AUTOSAR_CAN/EcucModuleDefs/CanConfigSet/CanHardwareObject/CANHandleType</DEFINITION-REF>
           <VALUE>FALSE</VALUE>
        </ECUC-TEXTUAL-PARAM-VALUES>
 </PARAMETER-VALUES>        
<ECUC-CONTAINER-VALUE>

我的 xml 中有大约 100 个<ECUC-CONTAINER-VALUE>标签。如果容器下面<ECUC-NUMERICAL-PARAM-VALUES>的文本是,我必须删除容器 但我没有得到结果。请帮助。<DEFINITION-REF DEST="ECUC-INTEGER-PARAM-DEF">/AUTOSAR_CAN/EcucModuleDefs/CanConfigSet/CanHardwareObject/CANIdValue

我写的脚本:

import xml.etree.ElementTree
tree = ET.parse('a.xml')
root = tree.getroot()

for child in root.findall(".//ECUC-NUMERICAL-PARAM-VALUE"):
    for gchild in child.findall(".//DEFINITION-REF [@DEST='ECUC-INTEGER-PARAM-DEF']"):
         string = gchild.find("VALUE").text
         if string == "/AUTOSAR_CAN/EcucModuleDefs/CanConfigSet/CanHardwareObject/CANIdValue":
             root.remove(child)

标签: pythonxmlelementtree

解决方案


如果要删除ECUC-NUMERICAL-PARAM-VALUES,则需要选择它的父级。所以尝试从PARAMETER-VALUES关卡中进行迭代。

例子...

XML 输入a.xml;更新为格式正确)

<doc>
    <ECUC-CONTAINER-VALUE>
        <SHORT-NAME>ABC</SHORT-NAME>
        <DEFINITION-REF DEST="ECUC-PARAM-CONF-CONTAINER-DEF">/AUTOSAR_CAN/EcucModuleDefs/CanConfigSet/CanHardwareObject</DEFINITION-REF>
        <PARAMETER-VALUES>
            <ECUC-NUMERICAL-PARAM-VALUES>
                <DEFINITION-REF DEST="ECUC-INTEGER-PARAM-DEF">/AUTOSAR_CAN/EcucModuleDefs/CanConfigSet/CanHardwareObject/CANIdValue</DEFINITION-REF>
                <VALUE>1053</VALUE>
            </ECUC-NUMERICAL-PARAM-VALUES>
            <ECUC-TEXTUAL-PARAM-VALUES>
                <DEFINITION-REF DEST="ECUC-ENUMERATION-PARAM-DEF">/AUTOSAR_CAN/EcucModuleDefs/CanConfigSet/CanHardwareObject/CANHandleType</DEFINITION-REF>
                <VALUE>TRUE</VALUE>
            </ECUC-TEXTUAL-PARAM-VALUES>
        </PARAMETER-VALUES>
    </ECUC-CONTAINER-VALUE>
    <ECUC-CONTAINER-VALUE>
        <SHORT-NAME>ABC</SHORT-NAME>
        <DEFINITION-REF DEST="ECUC-PARAM-CONF-CONTAINER-DEF">/AUTOSAR_CAN/EcucModuleDefs/CanConfigSet/CanHardwareObject</DEFINITION-REF>
        <PARAMETER-VALUES>
            <ECUC-NUMERICAL-PARAM-VALUES>
                <DEFINITION-REF DEST="ECUC-INTEGER-PARAM-DEF">/AUTOSAR_CAN/EcucModuleDefs/CanConfigSet/CanHardwareObject/CANIdValue</DEFINITION-REF>
                <VALUE>1054</VALUE>
            </ECUC-NUMERICAL-PARAM-VALUES>
            <ECUC-TEXTUAL-PARAM-VALUES>
                <DEFINITION-REF DEST="ECUC-ENUMERATION-PARAM-DEF">/AUTOSAR_CAN/EcucModuleDefs/CanConfigSet/CanHardwareObject/CANHandleType</DEFINITION-REF>
                <VALUE>FALSE</VALUE>
            </ECUC-TEXTUAL-PARAM-VALUES>
        </PARAMETER-VALUES>
    </ECUC-CONTAINER-VALUE>
</doc>

Python

import xml.etree.ElementTree as ET

tree = ET.parse('a.xml')

for p_vals in tree.findall(".//PARAMETER-VALUES"):
    for num_p_vals in p_vals.findall(".//ECUC-NUMERICAL-PARAM-VALUES"):
        def_ref = num_p_vals.find("DEFINITION-REF[@DEST='ECUC-INTEGER-PARAM-DEF']")
        if def_ref is not None and def_ref.text == \
                "/AUTOSAR_CAN/EcucModuleDefs/CanConfigSet/CanHardwareObject/CANIdValue":
            p_vals.remove(num_p_vals)

ET.dump(tree)

输出

<doc>
    <ECUC-CONTAINER-VALUE>
        <SHORT-NAME>ABC</SHORT-NAME>
        <DEFINITION-REF DEST="ECUC-PARAM-CONF-CONTAINER-DEF">/AUTOSAR_CAN/EcucModuleDefs/CanConfigSet/CanHardwareObject</DEFINITION-REF>
        <PARAMETER-VALUES>
            <ECUC-TEXTUAL-PARAM-VALUES>
                <DEFINITION-REF DEST="ECUC-ENUMERATION-PARAM-DEF">/AUTOSAR_CAN/EcucModuleDefs/CanConfigSet/CanHardwareObject/CANHandleType</DEFINITION-REF>
                <VALUE>TRUE</VALUE>
            </ECUC-TEXTUAL-PARAM-VALUES>
        </PARAMETER-VALUES>
    </ECUC-CONTAINER-VALUE>
    <ECUC-CONTAINER-VALUE>
        <SHORT-NAME>ABC</SHORT-NAME>
        <DEFINITION-REF DEST="ECUC-PARAM-CONF-CONTAINER-DEF">/AUTOSAR_CAN/EcucModuleDefs/CanConfigSet/CanHardwareObject</DEFINITION-REF>
        <PARAMETER-VALUES>
            <ECUC-TEXTUAL-PARAM-VALUES>
                <DEFINITION-REF DEST="ECUC-ENUMERATION-PARAM-DEF">/AUTOSAR_CAN/EcucModuleDefs/CanConfigSet/CanHardwareObject/CANHandleType</DEFINITION-REF>
                <VALUE>FALSE</VALUE>
            </ECUC-TEXTUAL-PARAM-VALUES>
        </PARAMETER-VALUES>
    </ECUC-CONTAINER-VALUE>
</doc>

如果您能够使用 lxml,它比 ElementTree 具有更好的 XPath 支持。您还可以使用 访问父元素getparent()。在我看来,这简化了答案。

示例...(与上述相同的输入产生与上述相同的输出)

from lxml import etree

tree = etree.parse('a.xml')

for num_p_vals in tree.xpath(".//ECUC-NUMERICAL-PARAM-VALUES[DEFINITION-REF[@DEST='ECUC-INTEGER-PARAM-DEF']='/AUTOSAR_CAN/EcucModuleDefs/CanConfigSet/CanHardwareObject/CANIdValue']"):
    num_p_vals.getparent().remove(num_p_vals)

etree.dump(tree.getroot())

推荐阅读