使用XSLT复制和移动子节点

时间:2014-09-19 16:08:54

标签: xml xslt

我有这个xsl脚本转换不正确的xml,从而将端口子项移动到正确的父主机

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="host">
        <xsl:variable name="hostname" select="@name"/>
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:apply-templates select="//host/port[@parent=$hostname]">
                 <xsl:sort select="@name" data-type="text" />
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>

错误的xml示例(某些端口未放置在其父级下)

    <hosts>
      <host modelID="1" name="H2">
         <port ID="H2.Port1" name="Port1" parent="H2" speed="100"/>
         <port ID="H2.Port2" name="Port2" parent="H2" speed="100"/>
         <port ID="H1.Port1" name="Port1" parent="H1" speed="100"/>
      </host>
      <host modelID="1" name="H1"/>
    </hosts>

期望的输出。

    <hosts>
       <host modelID="1" name="H2">
          <port ID="H2.Port1" name="Port1" parent="H2" speed="100"/>
          <port ID="H2.Port2" name="Port2" parent="H2" speed="100"/>
       </host>
       <host modelID="1" name="H1">
          <port ID="H1.Port1" name="Port1" parent="H1" speed="100"/>
       </host>
    </hosts>

现在,输入已更改,因此它包含一个新的端口元素。我想更改脚本以处理此问题并在输出中包含新元素。 新的理想输出。

   <hosts>
      <host modelID="1" name="H2">
         <ports>
            <port ID="H2.Port1" name="Port1" parent="H2" speed="100"/>
            <port ID="H2.Port2" name="Port2" parent="H2" speed="100"/>
         </ports> 
       </host>
       <host modelID="1" name="H1">
          <ports>
             <port ID="H1.Port1" name="Port1" parent="H1" speed="100"/>
          </ports>
       </host>
    </hosts>

我希望我只需要更改行

    <xsl:apply-templates select="//host/port[@parent=$hostname]">

    <xsl:apply-templates select="//host/ports/port[@parent=$hostname]">

为什么这不起作用,我需要做什么?

1 个答案:

答案 0 :(得分:1)

您在apply-templates中使用的XPath适用于输入文档,而不适用于您要创建的文档。所以看起来你需要这样做:

<xsl:template match="host">
    <xsl:variable name="hostname" select="@name"/>
    <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <ports>
            <xsl:apply-templates select="//host/ports/port[@parent=$hostname]">
                 <xsl:sort select="@name" data-type="text" />
            </xsl:apply-templates>
        </ports>
    </xsl:copy>
</xsl:template>