如何使用 XSLT 在 xml 文件中查找元素并将其放置在另一个标记中?
Posted
技术标签:
【中文标题】如何使用 XSLT 在 xml 文件中查找元素并将其放置在另一个标记中?【英文标题】:How to find an element in xml file and place that inside another tag using XSLT? 【发布时间】:2021-09-18 01:22:03 【问题描述】:我有一个xml文件ab.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="integration" />
</Parameters>
<Children>
<Group Name="Cam1">
<Parameters>
<Parameter Type="Integer" Name="maxA" />
<Parameter Type="Integer" Name="MaxB"/>
<Parameter Type="String" Name="MaxC" />
</Parameters>
<Children>
<Group Name="Field1">
<Parameters>
<Parameter Type="Integer" Name="maxA" />
<Parameter Type="Integer" Name="MaxB" Value="1600" />
<Parameter Type="String" Name="MaxC" />
</Parameters>
<Children>
<Test Name="Test1" Namespace="TestCases">
<Parameters>
<Parameter Type="Device" Name="Device">
<Requirements>
<Requirement TypeId="a76" Source="User" />
<Requirement TypeId="2c9" Source="User" />
</Requirements>
</Parameter>
</Parameters>
</Test>
</Children>
</Group>
<Group Name="Field3">
<Parameters>
<Parameter Type="Integer" Name="maxA" />
<Parameter Type="Integer" Name="MaxB" />
<Parameter Type="String" Name="MaxC" Value="51" />
</Parameters>
<Children>
<Test Name="Test5" Namespace="TestCases">
<Parameters>
<Parameter Type="Dev" Name="Dev">
<Requirements>
<Requirement TypeId="a76" Source="User" />
<Requirement TypeId="2c9" Source="User" />
</Requirements>
</Parameter>
</Parameters>
</Test>
</Children>
</Group>
</Children>
</Group>
</Children>
</Group>
<Models>
<Model Name="DD1" />
</Models>
</TestSuite>
我有这个 XSLT
<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="Group[@Name = 'TestRoot']/Children">
<xsl:copy>
<xsl:apply-templates select=".//Test"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
这给了我这个结果:- output.xml
<?xml version="1.0" encoding="UTF-8"?>
<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="integration"/>
</Parameters>
<Children>
<Test Name="Test1" Namespace="TestCases">
<Parameters>
<Parameter Type="Device" Name="Device">
<Requirements>
<Requirement TypeId="a76" Source="User"/>
<Requirement TypeId="2c9" Source="User"/>
</Requirements>
</Parameter>
</Parameters>
</Test>
<Test Name="Test5" Namespace="TestCases">
<Parameters>
<Parameter Type="Dev" Name="Dev">
<Requirements>
<Requirement TypeId="a76" Source="User"/>
<Requirement TypeId="2c9" Source="User"/>
</Requirements>
</Parameter>
</Parameters>
</Test>
</Children>
</Group>
<Models>
<Model Name="DD1"/>
</Models>
</TestSuite>
所以基本上 xslt 代码删除了在 TestRoot 组中定义的重复参数。因此,在 TestRoot Group 中定义的参数再次在其他组中定义,因此使用当前的 XSLT 代码,它基本上删除了所有子组及其参数,并将测试标签移动到子标签内。
点击Demo
但是如果你在 Field1 Group 中看到它的参数名称 MaxB 有一个 value 字段覆盖了 Group TestRoot 的上述参数。如果是这种情况,我想要的是复制该参数并将其粘贴到 Group Field1 下的测试标签中,对于 field3 Group 也是如此。
期望的输出:-
<?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="integration" />
</Parameters>
<Children>
<Test Name="Test1" Namespace="TestCases">
<Parameters>
<Parameter Type="Integer" Name="MaxB" Value="1600" />
<Parameter Type="Device" Name="Device">
<Requirements>
<Requirement TypeId="a76" Source="User" />
<Requirement TypeId="2c9" Source="User" />
</Requirements>
</Parameter>
</Parameters>
</Test>
<Test Name="Test5" Namespace="TestCases">
<Parameters>
<Parameter Type="String" Name="MaxC" Value="51" />
<Parameter Type="Dev" Name="Dev">
<Requirements>
<Requirement TypeId="a76" Source="User"/>
<Requirement TypeId="2c9" Source="User"/>
</Requirements>
</Parameter>
</Parameters>
</Test>
</Children>
</Group>
<Models>
<Model Name="DD1" />
</Models>
</TestSuite>
如何使用 XSLT 实现所需的输出?提前致谢
【问题讨论】:
【参考方案1】:我想你想添加一个模板
<xsl:template match="Test/Parameters">
<xsl:copy>
<xsl:apply-templates select="@* | ../../preceding-sibling::Parameters[1]/Parameter[@Value] | node()"/>
</xsl:copy>
</xsl:template>
【讨论】:
【参考方案2】:zykxPython,如果我理解正确,您想复制具有 @Value 属性的参数。在这种情况下,您可以添加与参数匹配的模板并添加这些参数。
<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="Group[@Name = 'TestRoot']/Children">
<xsl:copy>
<xsl:apply-templates select=".//Test"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Parameters[ancestor::Children]">
<xsl:copy>
<xsl:if test="ancestor::Group[1]/Parameters/Parameter[@Value]">
<xsl:copy-of select="ancestor::Group[1]/Parameters/Parameter[@Value]"/>
</xsl:if>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
样式表>
根据您的预期输出,您只需要匹配作为 Children 元素的祖先的参数。
如果它适合你,请告诉我。
谢谢, 瓦西尔
【讨论】:
以上是关于如何使用 XSLT 在 xml 文件中查找元素并将其放置在另一个标记中?的主要内容,如果未能解决你的问题,请参考以下文章
使用 Python 或 XSLT 将复杂的 XML 转换为 CSV