我有一个看起来像这样的XML
<executionPlan name="Test" >
<paramList>
<param name="param1" default=""/>
</paramList>
<varList>
<var name="bla" default=":[param1]"/>
</varList>
<simpleSteps limitToHostSet="bla">
<execNative>
<exec cmd="/bin/sh"/>
</execNative>
</simpleSteps>
我需要将其转换为如下所示:
<executionPlan name="Test" >
<paramList>
<param name="param1" default=""/>
</paramList>
<simpleSteps limitToHostSet="bla">
<varList>
<var name="bla" default=":[param1]"/>
</varList>
<execNative>
<exec cmd="/bin/sh"/>
</execNative>
</simpleSteps>
正如您所看到的,varList元素需要嵌套在开始标记后面的simpleSteps元素中。在simpleSteps中可能还有其他varList元素,不能更改。
如何使用XSLT实现这一目标?我是XSLT的新手,并且徒劳地试了一整天...真的很感激任何帮助。
鲁兹
答案 0 :(得分:4)
以下样式表:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="varList[following-sibling::*[1][self::simpleSteps]]" />
<xsl:template match="simpleSteps">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:copy-of select="preceding-sibling::varList[1]" />
<xsl:apply-templates select="node()" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
在此输入上:
<executionPlan name="Test">
<paramList>
<param name="param1" default="" />
</paramList>
<varList>
<var name="bla" default=":[param1]" />
</varList>
<varList>
<var name="bla2" default=":[param2]" />
</varList>
<simpleSteps limitToHostSet="bla">
<execNative>
<exec cmd="/bin/sh" />
</execNative>
</simpleSteps>
</executionPlan>
产地:
<executionPlan name="Test">
<paramList>
<param name="param1" default="" />
</paramList>
<varList>
<var name="bla" default=":[param1]" />
</varList>
<simpleSteps limitToHostSet="bla">
<varList>
<var name="bla2" default=":[param2]" />
</varList>
<execNative>
<exec cmd="/bin/sh" />
</execNative>
</simpleSteps>
</executionPlan>
修改:只有紧接在前的varList
移入其关联的simpleSteps
。所有其他varList
元素都将保持不变。
我突然不清楚这是否是所需的行为,或者varList
元素中是否有多个simpleSteps
元素应该保持不变。请参阅我原来的解决方案:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="varList" />
<xsl:template match="simpleSteps">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:copy-of select="../varList" />
<xsl:apply-templates select="node()" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
在此输入上:
<executionPlan name="Test">
<paramList>
<param name="param1" default="" />
</paramList>
<varList>
<var name="bla" default=":[param1]" />
</varList>
<simpleSteps limitToHostSet="bla">
<varList>
<var name="bla7" default=":[param7]" />
</varList>
<execNative>
<exec cmd="/bin/sh" />
</execNative>
</simpleSteps>
</executionPlan>
产地:
<executionPlan name="Test">
<paramList>
<param name="param1" default="" />
</paramList>
<simpleSteps limitToHostSet="bla">
<varList>
<var name="bla" default=":[param1]" />
</varList>
<varList>
<var name="bla7" default=":[param7]" />
</varList>
<execNative>
<exec cmd="/bin/sh" />
</execNative>
</simpleSteps>
</executionPlan>
答案 1 :(得分:2)
这是一个更简单,更简洁的解决方案:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="simpleSteps/*[1]">
<xsl:copy-of select="/*/varList[1]"/>
<xsl:call-template name="identity"/>
</xsl:template>
<xsl:template match="/*/varList[1]"/>
</xsl:stylesheet>
应用于提供的XML文档时:
<executionPlan name="Test" >
<paramList>
<param name="param1" default=""/>
</paramList>
<varList>
<var name="bla" default=":[param1]"/>
</varList>
<simpleSteps limitToHostSet="bla">
<execNative>
<exec cmd="/bin/sh"/>
</execNative>
</simpleSteps>
</executionPlan>
产生了正确的,正确的结果:
<executionPlan name="Test">
<paramList>
<param name="param1" default=""/>
</paramList>
<simpleSteps limitToHostSet="bla">
<varList>
<var name="bla" default=":[param1]"/>
</varList>
<execNative>
<exec cmd="/bin/sh"/>
</execNative>
</simpleSteps>
</executionPlan>
<强>解释强>:
identity rule /模板“按原样”复制每个节点。只有两个例外,如下所述。
仅匹配top元素的第一个varList
子元素的覆盖模板没有正文 - 这有效地取消了此元素的标识模板的复制操作。
与simpleSteps
的第一个元素子元素匹配的覆盖模板执行两项操作:a)它复制所需的varList
(顶部元素的子元素)元素,然后b)调用它身份模板将自身复制到输出。