将当前节点传递给调用模板

时间:2016-03-11 12:05:07

标签: xml xslt

如何将当前处理的节点从模板传递给for-call中的每个选择?

这是我的输入XML示例:

<?xml version="1.0" encoding="UTF-8"?>
<Node>
    <Node>
        <OtherNode testname="1.a"/>
        <Node/>
        <OtherNode testname="2.a"/>
        <Node/>
        <OtherNode testname="1.c"/>
        <Node/>
    </Node>
    <Node>  
        <OtherNode testname="3.a"/>
        <Node/>
        <OtherNode testname="1.b"/>
        <Node/>
    </Node>
</Node>

输出我想得到:

<?xml version="1.0" encoding="UTF-8"?>
<Node>
    <Node>
        <OtherNode testname="1.c"/>
        <Node/>
        <OtherNode testname="1.a"/>
        <Node/>
        <OtherNode testname="2.a"/>
        <Node/>     
        <Group testname="aGroup"/>
        <Node>
            <OtherNode testname="1.a"/>
            <Node/>
            <OtherNode testname="2.a"/>
            <Node/>
        </Node>
    </Node>
    <Node>  
        <OtherNode testname="1.b"/>
        <Node/>
        <OtherNode testname="3.a"/>
        <Node/>     
        <Group testname="aGroup"/>
        <Node>
            <OtherNode testname="3.a"/>
            <Node/>
        </Node>
    </Node>
</Node>

XSLT我正在使用:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0">
<xsl:output method="xml" indent="yes"/>

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

    <xsl:template name="Move_a">
        <xsl:for-each select="//Node/*|@*">
            <xsl:if test="(name()='OtherNode') and contains(@testname,'.a')">
                <xsl:copy>
                    <xsl:apply-templates select = "node()|@*"/>
                </xsl:copy>
            </xsl:if>
            <xsl:if test="(name()='Node') and preceding-sibling::OtherNode[1][contains(@testname,'.a')]">
                <xsl:copy>
                    <xsl:apply-templates select = "node()|@*"/>
                </xsl:copy>
            </xsl:if>
        </xsl:for-each> 
    </xsl:template>

    <xsl:template match="//Node[OtherNode[contains(@testname,'.b') or contains(@testname,'.c')]]">
        <xsl:copy>
            <Group testname="aGroup"/>
            <Node>
                <xsl:call-template name="Move_a"/>
            </Node>
        </xsl:copy> 
    </xsl:template> 

  </xsl:stylesheet>

我现在以某种方式需要更改<xsl:for-each select="//Node/*|@*">的选择以仅选择当前匹配的节点(在最后一个模板中),但我无法弄清楚如何。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

您可以使用以下样式表来实现输出:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0">
    <xsl:output method="xml" indent="yes"/>

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

    <xsl:template match="Node[OtherNode]">
        <xsl:copy>
            <xsl:apply-templates select="OtherNode[not(ends-with(@testname, 'a'))]|OtherNode[not(ends-with(@testname, 'a'))]/following-sibling::*[1]"/>
            <xsl:apply-templates select="OtherNode[ends-with(@testname, 'a')]|OtherNode[ends-with(@testname, 'a')]/following-sibling::*[1]"/>
            <Group testname="aGroup"/>
            <Node>
                <xsl:for-each select="OtherNode[ends-with(@testname, 'a')]">
                    <xsl:copy-of select="."/>
                    <xsl:apply-templates select="following-sibling::*[1]"/>
                </xsl:for-each>
            </Node>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>