如何使用 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 的 lxml
(etree
的扩展第三方版本)支持 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>
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)
我有多个 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 的 lxml
(etree
的扩展第三方版本)支持 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>
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)