如何使用 python 将特定 xml 标签移动到新的 xml 文件?

How to move a specific xml tag to a new xml file using python?

我有多个 xml 文件类似于下面的文件:- 名称 = 已更新 input.xml

<?xml version="1.0"?>
<TestSuite Name="A123">
 <Group Name="TestRoot" ExecutionPolicy="AnyDeviceAnyOrder">
  <Parameters>
      <Parameter Type="Integer" Name="maxA" Value="1" />
      <Parameter Type="Integer" Name="MaxB" Value="120" />
      <Parameter Type="String" Name="MaxC" Value="master" />
  </Parameters> 
  <Children>
          <Test Name="TestCam" Namespace="TestCase">
              <Parameters>
                    <Parameter Type="Integer" Name="maxTooth" />
              </Parameters>
          </Test>
  </Children>
  <Group Name="TestMain" ExecutionPolicy="AnyDeviceAnyOrder">
  <Parameters>
      <Parameter Type="Integer" Name="maxA" Value="1" />
      <Parameter Type="Integer" Name="MaxB" Value="120" />
      <Parameter Type="String" Name="MaxC" Value="master" />
  </Parameters> 
      <Group Name="TestMain1" ExecutionPolicy="AnyDeviceAnyOrder">
          <Parameters>
              <Parameter Type="Integer" Name="maxA" Value="1" />
              <Parameter Type="Integer" Name="MaxB" Value="120" />
              <Parameter Type="String" Name="MaxC" Value="master" />
          </Parameters> 
          <Children>
              <Test Name="TestDriver1" Namespace="TestCase">
                  <Parameters>
                        <Parameter Type="Integer" Name="maxP" />
                  </Parameters>
              </Test>
          </Children>
      </Group>
  <Children>
          <Test Name="TestDriver" Namespace="TestCase">
              <Parameters>
                    <Parameter Type="Integer" Name="maxP" />
              </Parameters>
          </Test>
          <Test Name="TestField" Namespace="TestCase">
              <Parameters>
                    <Parameter Type="Integer" Name="maxP" />
                       <Requirements>
                         <Requirement TypeId = "Abcdef" Source = "User1" >
                         <Requirement TypeId = "ghijk" Source = "User1" >
                       </Requirements>
              </Parameters>
          </Test>
  </Children>      
  </Group>      
 </Group>
 <Models>
     <Model Name= "NewPhone"> 
 </Models>
</TestSuite>

我有一个 python 代码,它正在创建一个新的 xml 文件,其中只有一些标签 如下所示 file1_sorted.xml:-

<?xml version="1.0"?>
<TestSuite Name="DM123">
  <Group Name="TestRoot" ExecutionPolicy="AnyDeviceAnyOrder">
  <Parameters>
      <Parameter Type="Integer" Name="maxA" Value="1" />
      <Parameter Type="Integer" Name="MaxB" Value="120" />
      <Parameter Type="String" Name="MaxC" Value="master" />
  </Parameters>     
  </Group>
  <Models>
      <Model Name= "NewPhone"> 
  </Models>
</TestSuite>

所以基本上它删除了 children 标签。代码如下:-

import os
import xml.etree.ElementTree as ET

def removeChild(fn):
    tree = ET.parse(fn + '.xml')
    root = tree.getroot()
    for grp in root.findall('Group'):
        ch = grp.find('Children')
        grp.remove(ch)
    with open(fn + '_sorted.xml', 'w') as f:
        tree.write(f, encoding='unicode')

path = r"C:\Users\xml_files"

for filename in os.listdir(path):
    if filename.endswith(".xml"):
        fname = os.path.splitext(filename)[0]
        print(fname)
        removeChild(fname)

现在我要做的是将 Test 标签移到 children 标签中,但不要重复参数。正如您在文件 input.xml 中看到的那样,有一个 Sub Group TestMain,它包含与 Parent Group TestRoot 相同的参数。我想删除子组及其参数但不删除测试标签。

像这样output.xml:-

<?xml version="1.0"?>
<TestSuite Name="DM123">
  <Group Name="TestRoot" ExecutionPolicy="AnyDeviceAnyOrder">
  <Parameters>
      <Parameter Type="Integer" Name="maxA" Value="1" />
      <Parameter Type="Integer" Name="MaxB" Value="120" />
      <Parameter Type="String" Name="MaxC" Value="master" />
  </Parameters>
  <Children>
      <Test Name="TestCam" Namespace="TestCase">
              <Parameters>
                    <Parameter Type="Integer" Name="maxTooth" />
              </Parameters>
      </Test>
      <Test Name="TestDriver" Namespace="TestCase">
              <Parameters>
                    <Parameter Type="Integer" Name="maxP" />
              </Parameters>
          </Test>
      <Test Name="TestField" Namespace="TestCase">
              <Parameters>
                    <Parameter Type="Integer" Name="maxP" />
                       <Requirements>
                         <Requirement TypeId = "Abcdef" Source = "User1" >
                         <Requirement TypeId = "ghijk" Source = "User1" >
                       </Requirements>
              </Parameters>
      </Test>
  </Children>     
  </Group>
  <Models>
      <Model Name= "NewPhone"> 
  </Models>
</TestSuite>

我怎样才能达到这个期望output.xml?提前致谢

对于广泛的 XML 转换,如跨不同级别组合节点,请考虑 XSLT,设计用于转换 XML 文件的专用语言。 Python 的 lxmletree 的扩展第三方版本)支持 XPath 1.0 和 XSLT 1.0。

XSLT (下面另存为.xsl文件,一个特殊的.xml文件)

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" omit-xml-declaration="no" indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="node()|@*">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
  </xsl:template>
    
  <xsl:template match="TestSuite/Group">
     <xsl:copy>
       <xsl:apply-templates select="Parameters"/>
       <xsl:apply-templates select="Children"/>
     </xsl:copy>
  </xsl:template>
    
  <xsl:template match="TestSuite/Group/Children">
     <xsl:copy>
       <xsl:apply-templates select="*"/>
       <xsl:apply-templates select="following-sibling::Group/Children/*"/>
     </xsl:copy>
  </xsl:template>
    
</xsl:stylesheet>

Online Demo

Python(使用第三方lxml

import os
import lxml.etree as ET

# LOAD XSLT SCRIPT
xsl = ET.parse(r"C:\Path\To\Script.xsl")

# CONFIGURE TRANSFORMER
transformer = ET.XSLT(xsl)

# ITERATIVELY TRANSFORM AND SAVE RESULT
path = r"C:\Users\xml_files"
for filename in os.listdir(path):
    if filename.endswith(".xml"):
        doc = ET.parse(os.path.join(path, filename))
        xsl_result = transformer(doc)

        new_file = os.path.join(path, filename.replace(".xml", "_new.xml"))
        with open(new_file, 'wb') as f:
            f.write(xsl_result)