2

我正在尝试编写一个 Python 脚本,该脚本将遍历文件并删除特定节点属性的容器。例如,我的树看起来像:

<collection shelf="New Arrivals">
  <ECUC-NUMERICAL-PARAM-VALUE>
    <SHORT-NAME>RTE_ABC</SHORT-NAME>
    <DEFINITION-REF DEST="ECUC-BOOLEAN-PARAM-DEF">/AUTOSAR/EcucDefs/Com/ComConfig/ComIPdu/ComIPduCancellationSupport</DEFINITION-REF>
  </ECUC-NUMERICAL-PARAM-VALUE>
  <ECUC-NUMERICAL-PARAM-VALUE>
    <SHORT-NAME>RTE_ABC</SHORT-NAME>
    <DEFINITION-REF DEST="ECUC-BOOLEAN-PARAM-DEF">/AUTOSAR/EcucDefs/Com/ComConfig/ComIPdu/xyz</DEFINITION-REF>
  </ECUC-NUMERICAL-PARAM-VALUE>
  <ECUC-NUMERICAL-PARAM-VALUE>
    <SHORT-NAME>RTE_ABC</SHORT-NAME>
    <DEFINITION-REF DEST="ECUC-BOOLEAN-PARAM-DEF">/AUTOSAR/EcucDefs/Com/ComConfig/ComIPdu/ComIPduCancellationSupport</DEFINITION-REF>
  </ECUC-NUMERICAL-PARAM-VALUE>
  <ECUC-NUMERICAL-PARAM-VALUE>
    <SHORT-NAME>RTE_ABC</SHORT-NAME>
    <DEFINITION-REF DEST="ECUC-BOOLEAN-PARAM-DEF">/AUTOSAR/EcucDefs/Com/ComConfig/ComIPdu/xyz</DEFINITION-REF>
  </ECUC-NUMERICAL-PARAM-VALUE>
  <ECUC-NUMERICAL-PARAM-VALUE>
    <SHORT-NAME>RTE_ABC</SHORT-NAME>
    <DEFINITION-REF DEST="ECUC-BOOLEAN-PARAM-DEF">/AUTOSAR/EcucDefs/Com/ComConfig/ComIPdu/ComIPduCancellationSupport</DEFINITION-REF>
  </ECUC-NUMERICAL-PARAM-VALUE>
</collection>

第一季度

<DEFINITION-REF DEST="ECUC-BOOLEAN-PARAM-DEF">如果子节点的属性等于,则应删除整个容器:/AUTOSAR/EcucDefs/Com/ComConfig/ComIPdu/ComIPduCancellationSupport

我写的脚本是:

import xml.etree.ElementTree as ET
tree = ET.parse('autosar1.xml')
root = tree.getroot()
for child in root.findall(".//ECUC-NUMERICAL-PARAM-VALUE"):
    for z in child.findall(".//DEFINITION-REF[@DEST='ECUC-BOOLEAN-PARAM-DEF']"):
        if z.text == "/AUTOSAR/EcucDefs/Com/ComConfig/ComIPdu/ComIPduCancellationSupport":
            child.remove(z)         
tree.write('output.xml')

但我没有得到预期的结果。我得到的结果是:

<collection shelf="New Arrivals">
<ECUC-NUMERICAL-PARAM-VALUE>
<SHORT-NAME>RTE_ABC</SHORT-NAME>
</ECUC-NUMERICAL-PARAM-VALUE>

<ECUC-NUMERICAL-PARAM-VALUE>
<SHORT-NAME>RTE_ABC</SHORT-NAME>
</ECUC-NUMERICAL-PARAM-VALUE>

<ECUC-NUMERICAL-PARAM-VALUE>
<SHORT-NAME>RTE_ABC</SHORT-NAME>
</ECUC-NUMERICAL-PARAM-VALUE>

<ECUC-NUMERICAL-PARAM-VALUE>
<SHORT-NAME>RTE_ABC</SHORT-NAME>
</ECUC-NUMERICAL-PARAM-VALUE>

<ECUC-NUMERICAL-PARAM-VALUE>
<SHORT-NAME>RTE_ABC</SHORT-NAME>
</ECUC-NUMERICAL-PARAM-VALUE>
</collection>

我想得到的结果:

<collection shelf="New Arrivals">
  <ECUC-NUMERICAL-PARAM-VALUE>
    <SHORT-NAME>RTE_ABC</SHORT-NAME>
    <DEFINITION-REF DEST="ECUC-BOOLEAN-PARAM-DEF">/AUTOSAR/EcucDefs/Com/ComConfig/ComIPdu/xyz</DEFINITION-REF>
  </ECUC-NUMERICAL-PARAM-VALUE>
  <ECUC-NUMERICAL-PARAM-VALUE>
    <SHORT-NAME>RTE_ABC</SHORT-NAME>
    <DEFINITION-REF DEST="ECUC-BOOLEAN-PARAM-DEF">/AUTOSAR/EcucDefs/Com/ComConfig/ComIPdu/xyz</DEFINITION-REF>
  </ECUC-NUMERICAL-PARAM-VALUE>
</collection>

第二季度

代替硬编码if条件中的节点属性,是否有可能通过获取用户输入(可能在命令提示符中),假设为"ComIPduCancellationSupport",(而不是整个属性为"/AUTOSAR/EcucDefs/Com/ComConfig/ComIPdu/ComIPduCancellationSupport"),实现所需的输出。

非常感谢。

4

1 回答 1

1

考虑第三方lxml它是用于处理 Python 语言中的 XML 和 HTML 的功能最丰富且易于使用的库。对于 Windows ,您可以使用 pip 或二进制文件进行安装。推荐的原因是该模块可以运行完全符合 W3C 的 XPath 1.0 和 XSLT 1.0,后者 XSLT 对您很有用。

XSLT是一种专用语言,可以转换 XML 文件,例如有条件地删除节点。特别是在 XSLT 中,我们运行身份转换(按原样复制整个文档),然后在我们打算删除的节点上运行一个空模板。请注意使用contains()来检查该节点文本中任何位置的字符串。这种方法不需要for循环或逻辑。if

使用 Python 的 lxml,我们可以从字符串构建动态 XSLT 脚本(顺便说一下,它是一个 XML 文件),并将诸如COMPU-METHOD-REF 之类的字符串传递到contains(). 这样的字符串可以来自用户输入。注意{0}string 的占位符.format()

Python

import lxml.etree as et
doc = et.parse('Input.xml')

xsl_str='''<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                                         xmlns:doc="http://autosar.org/3.0.2">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <!-- IDENTITY TRANSFORM -->
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <!-- EMPTY TEMPLATE -->
  <xsl:template match="INTEGER-TYPE[descendant::COMPU-METHOD-REF/@DEST='COMPU-METHOD' and 
                                    contains(descendant::COMPU-METHOD-REF, '{0}')]">    
  </xsl:template>

</xsl:stylesheet>'''

# LOAD DYNAMIC XSL STRING (PASSING BELOW STRING INTO ABOVE)
xsl = et.fromstring(xsl_str.format('CoolantTemp_T'))

transform = et.XSLT(xsl)
result = transform(doc)

# OUTPUT TO SCREEN
print(result)    
# OUTPUT TO FILE
with open('output.xml', 'wb') as f:
    f.write(result)

输出

<?xml version="1.0"?>
<TOP-LEVEL-PACKAGES>
  <AR-PACKAGE>
    <SHORT-NAME>DataType</SHORT-NAME>
    <ELEMENTS>
      <INTEGER-TYPE>
        <SHORT-NAME>EngineSpeed_T</SHORT-NAME>
        <SW-DATA-DEF-PROPS>
          <COMPU-METHOD-REF DEST="COMPU-METHOD">/DataType/DataTypeSemantics/EngineSpeed_T</COMPU-METHOD-REF>
        </SW-DATA-DEF-PROPS>
        <LOWER-LIMIT INTERVAL-TYPE="CLOSED">0</LOWER-LIMIT>
        <UPPER-LIMIT INTERVAL-TYPE="CLOSED">65535</UPPER-LIMIT>
      </INTEGER-TYPE>
      <INTEGER-TYPE>
        <SHORT-NAME>VehicleSpeed_T</SHORT-NAME>
        <SW-DATA-DEF-PROPS>
          <COMPU-METHOD-REF DEST="COMPU-METHOD">/DataType/DataTypeSemantics/VehicleSpeed_T</COMPU-METHOD-REF>
        </SW-DATA-DEF-PROPS>
        <LOWER-LIMIT INTERVAL-TYPE="CLOSED">0</LOWER-LIMIT>
        <UPPER-LIMIT INTERVAL-TYPE="CLOSED">65535</UPPER-LIMIT>
      </INTEGER-TYPE>
      <INTEGER-TYPE>
        <SHORT-NAME>Percent_T</SHORT-NAME>
        <SW-DATA-DEF-PROPS>
          <COMPU-METHOD-REF DEST="COMPU-METHOD">/DataType/DataTypeSemantics/Percent_T</COMPU-METHOD-REF>
        </SW-DATA-DEF-PROPS>
        <LOWER-LIMIT INTERVAL-TYPE="CLOSED">0</LOWER-LIMIT>
        <UPPER-LIMIT INTERVAL-TYPE="CLOSED">255</UPPER-LIMIT>
      </INTEGER-TYPE>
    </ELEMENTS>
    <SUB-PACKAGES>
      <AR-PACKAGE>
        <SHORT-NAME>DataTypeSemantics</SHORT-NAME>
        <ELEMENTS>
          <COMPU-METHOD>
            <SHORT-NAME>EngineSpeed_T</SHORT-NAME>
            <UNIT-REF DEST="UNIT">/DataType/DataTypeUnits/rpm</UNIT-REF>
            <COMPU-INTERNAL-TO-PHYS>
              <COMPU-SCALES>
                <COMPU-SCALE>
                  <COMPU-RATIONAL-COEFFS>
                    <COMPU-NUMERATOR>
                      <V>0</V>
                      <V>1</V>
                    </COMPU-NUMERATOR>
                    <COMPU-DENOMINATOR>
                      <V>8</V>
                    </COMPU-DENOMINATOR>
                  </COMPU-RATIONAL-COEFFS>
                </COMPU-SCALE>
              </COMPU-SCALES>
            </COMPU-INTERNAL-TO-PHYS>
          </COMPU-METHOD>
          <COMPU-METHOD>
            <SHORT-NAME>VehicleSpeed_T</SHORT-NAME>
            <UNIT-REF DEST="UNIT">/DataType/DataTypeUnits/kph</UNIT-REF>
            <COMPU-INTERNAL-TO-PHYS>
              <COMPU-SCALES>
                <COMPU-SCALE>
                  <COMPU-RATIONAL-COEFFS>
                    <COMPU-NUMERATOR>
                      <V>0</V>
                      <V>1</V>
                    </COMPU-NUMERATOR>
                    <COMPU-DENOMINATOR>
                      <V>64</V>
                    </COMPU-DENOMINATOR>
                  </COMPU-RATIONAL-COEFFS>
                </COMPU-SCALE>
              </COMPU-SCALES>
            </COMPU-INTERNAL-TO-PHYS>
          </COMPU-METHOD>
          <COMPU-METHOD>
            <SHORT-NAME>Percent_T</SHORT-NAME>
            <UNIT-REF DEST="UNIT">/DataType/DataTypeUnits/Percent</UNIT-REF>
            <COMPU-INTERNAL-TO-PHYS>
              <COMPU-SCALES>
                <COMPU-SCALE>
                  <COMPU-RATIONAL-COEFFS>
                    <COMPU-NUMERATOR>
                      <V>0</V>
                      <V>0.4</V>
                    </COMPU-NUMERATOR>
                    <COMPU-DENOMINATOR>
                      <V>1</V>
                    </COMPU-DENOMINATOR>
                  </COMPU-RATIONAL-COEFFS>
                </COMPU-SCALE>
              </COMPU-SCALES>
            </COMPU-INTERNAL-TO-PHYS>
          </COMPU-METHOD>
          <COMPU-METHOD>
            <SHORT-NAME>CoolantTemp_T</SHORT-NAME>
            <UNIT-REF DEST="UNIT">/DataType/DataTypeUnits/DegreeC</UNIT-REF>
            <COMPU-INTERNAL-TO-PHYS>
              <COMPU-SCALES>
                <COMPU-SCALE>
                  <COMPU-RATIONAL-COEFFS>
                    <COMPU-NUMERATOR>
                      <V>-40</V>
                      <V>1</V>
                    </COMPU-NUMERATOR>
                    <COMPU-DENOMINATOR>
                      <V>2</V>
                    </COMPU-DENOMINATOR>
                  </COMPU-RATIONAL-COEFFS>
                </COMPU-SCALE>
              </COMPU-SCALES>
            </COMPU-INTERNAL-TO-PHYS>
          </COMPU-METHOD>
        </ELEMENTS>
      </AR-PACKAGE>
      <AR-PACKAGE>
        <SHORT-NAME>DataTypeUnits</SHORT-NAME>
        <ELEMENTS>
          <UNIT>
            <SHORT-NAME>rpm</SHORT-NAME>
            <DISPLAY-NAME>rpm</DISPLAY-NAME>
          </UNIT>
          <UNIT>
            <SHORT-NAME>kph</SHORT-NAME>
            <DISPLAY-NAME>kph</DISPLAY-NAME>
          </UNIT>
          <UNIT>
            <SHORT-NAME>Percent</SHORT-NAME>
            <DISPLAY-NAME>Percent</DISPLAY-NAME>
          </UNIT>
          <UNIT>
            <SHORT-NAME>DegreeC</SHORT-NAME>
            <DISPLAY-NAME>DegreeC</DISPLAY-NAME>
          </UNIT>
        </ELEMENTS>
      </AR-PACKAGE>
    </SUB-PACKAGES>
  </AR-PACKAGE>
</TOP-LEVEL-PACKAGES>
于 2017-09-26T16:33:14.197 回答