【问题标题】:Passing current node to call-template将当前节点传递给调用模板
【发布时间】:2016-03-11 12:05:07
【问题描述】:

如何将当前处理的节点从模板传递到调用模板中的 for-each 选择?

这是我的输入 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>

我现在不知何故需要更改 &lt;xsl:for-each select="//Node/*|@*"&gt; 的选择以仅选择当前匹配的节点(在最后一个模板中),但我不知道如何。任何帮助将不胜感激。

【问题讨论】:

    标签: xml xslt


    【解决方案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>
    

    【讨论】:

    • 在完全理解了您的代码之后,我能够将它应用到我真正的 xml 中,它就像一个魅力一样,谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-07
    • 2023-02-13
    • 1970-01-01
    • 2021-06-29
    • 2023-03-21
    • 1970-01-01
    • 2018-02-06
    相关资源
    最近更新 更多