Удалить контейнер в XML - PullRequest
0 голосов
/ 27 ноября 2018

Это мой входной файл. Намеренно пропустил заголовки, так как я думал, что они не касаются вопроса. Я не вставил весь файл, так как он огромен. Я добавил только два контейнера:

  <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>

У меня есть около 100 <ECUC-CONTAINER-VALUE> тегов в моем XML.Я должен удалить контейнер <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)

1 Ответ

0 голосов
/ 27 ноября 2018

Если вы хотите удалить 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())
...