【问题标题】:Remove a container in XML删除 XML 中的容器
【发布时间】:2018-11-27 18:18:01
【问题描述】:

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

  <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 个 &lt;ECUC-CONTAINER-VALUE&gt; 标记。如果&lt;DEFINITION-REF DEST="ECUC-INTEGER-PARAM-DEF"&gt; 容器下面的文本是/AUTOSAR_CAN/EcucModuleDefs/CanConfigSet/CanHardwareObject/CANIdValue,我必须删除&lt;ECUC-NUMERICAL-PARAM-VALUES&gt; 容器 但我没有得到结果。请帮助。

我写的脚本:

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)

【问题讨论】:

  • 我同意,我认为没有理由投反对票。但是,拥有Minimal, Complete, and Verifiable example 会很有帮助。您问题中的 XML 格式不正确,因为它没有单个根元素。 (我还没有检查是否还有其他问题。)您可以更新您的 XML 以使其格式正确吗?在 ECUC-CONTAINER-VALUE 的祖先中包含任何默认命名空间 (xmlns="...") 尤其重要。
  • @DanielHaley 感谢您的意见。我没有粘贴整个文件。我只添加了两个容器。已编辑。
  • 我的回答有帮助还是您还有问题?

标签: python xml elementtree


【解决方案1】:

如果你想删除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,那么它对 XPath 的支持要比 ElementTree 好得多。您还可以使用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())

【讨论】:

    猜你喜欢
    • 2011-09-23
    • 1970-01-01
    • 2020-02-17
    • 1970-01-01
    • 2021-05-28
    • 2018-10-31
    • 1970-01-01
    • 2022-11-10
    • 2017-08-11
    相关资源
    最近更新 更多