使用xslt将xml元素移动到另一个元素中

时间:2011-04-14 15:27:26

标签: xslt elements nested

我有一个看起来像这样的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的新手,并且徒劳地试了一整天...真的很感激任何帮助。

鲁兹

2 个答案:

答案 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>

<强>解释

  1. identity rule /模板“按原样”复制每个节点。只有两个例外,如下所述。

  2. 仅匹配top元素的第一个varList子元素的覆盖模板没有正文 - 这有效地取消了此元素的标识模板的复制操作。

  3. simpleSteps的第一个元素子元素匹配的覆盖模板执行两项操作:a)它复制所需的varList(顶部元素的子元素)元素,然后b)调用它身份模板将自身复制到输出。

相关问题