Recursion 将模板重新应用于XSLT中其他模板的输出

Recursion 将模板重新应用于XSLT中其他模板的输出,recursion,xslt-1.0,Recursion,Xslt 1.0,下面应该是简单或不可能做到的,但现在我不知道如何做到,所以我问。在我的XSLT中,我有生成元素的模板,这些元素应该再次被转换。更精确的是,每当模板输出一个在原始输入中将要进行转换的元素时,它应该再次进行转换。所以无限循环是可能的,但要通过仔细设计模板来避免。举个例子: input.xml <?xml version="1.0" encoding="utf-8" ?> <example> <a /> <b /> </exampl

下面应该是简单或不可能做到的,但现在我不知道如何做到,所以我问。在我的XSLT中,我有生成元素的模板,这些元素应该再次被转换。更精确的是,每当模板输出一个在原始输入中将要进行转换的元素时,它应该再次进行转换。所以无限循环是可能的,但要通过仔细设计模板来避免。举个例子:

input.xml

<?xml version="1.0" encoding="utf-8" ?>
<example>
    <a />
    <b />
</example>

transform.xsl

<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform 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="a">a</xsl:template>

    <xsl:template match="b">
        <B>b <a /></B>
    </xsl:template>
</xsl:transform>

A.
B
current-output.xml

<?xml version="1.0"?>
<example>
    a
    <B>b <a/></B>
</example>
<?xml version="1.0"?>
<example>
    a
    <B>b a</B>
</example>

A.
B
所需的-output.xml

<?xml version="1.0"?>
<example>
    a
    <B>b <a/></B>
</example>
<?xml version="1.0"?>
<example>
    a
    <B>b a</B>
</example>

A.
b a
只有一次转换(如果有的话)才能实现这一目标的最佳解决方案是什么?

这是一个两次转换,可以产生想要的结果:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common" exclude-result-prefixes="ext">

 <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="/">
  <xsl:variable name="vrtfPass1">
    <xsl:apply-templates/>
  </xsl:variable>

  <xsl:variable name="vPass1" select="ext:node-set($vrtfPass1)/*"/>

  <xsl:apply-templates select="$vPass1" mode="pass2"/>
 </xsl:template>

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

 <xsl:template match="replace">
  <xsl:text>&#xA;Hello world&#xA;</xsl:text>
 </xsl:template>

 <xsl:template match="@*|node()" mode="pass2">
  <xsl:call-template name="identity"/>
 </xsl:template>
</xsl:stylesheet>
<example>
    <content>Lorem ipsum</content>
    <content><replace /></content>
</example>
<example>
   <wrapper>
Hello world
Lorem ipsum</wrapper>
   <wrapper>
Hello world

Hello world
</wrapper>
</example>


;世界你好
;
应用于提供的XML文档时

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common" exclude-result-prefixes="ext">

 <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="/">
  <xsl:variable name="vrtfPass1">
    <xsl:apply-templates/>
  </xsl:variable>

  <xsl:variable name="vPass1" select="ext:node-set($vrtfPass1)/*"/>

  <xsl:apply-templates select="$vPass1" mode="pass2"/>
 </xsl:template>

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

 <xsl:template match="replace">
  <xsl:text>&#xA;Hello world&#xA;</xsl:text>
 </xsl:template>

 <xsl:template match="@*|node()" mode="pass2">
  <xsl:call-template name="identity"/>
 </xsl:template>
</xsl:stylesheet>
<example>
    <content>Lorem ipsum</content>
    <content><replace /></content>
</example>
<example>
   <wrapper>
Hello world
Lorem ipsum</wrapper>
   <wrapper>
Hello world

Hello world
</wrapper>
</example>

乱数假文
生成所需的正确结果

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common" exclude-result-prefixes="ext">

 <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="/">
  <xsl:variable name="vrtfPass1">
    <xsl:apply-templates/>
  </xsl:variable>

  <xsl:variable name="vPass1" select="ext:node-set($vrtfPass1)/*"/>

  <xsl:apply-templates select="$vPass1" mode="pass2"/>
 </xsl:template>

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

 <xsl:template match="replace">
  <xsl:text>&#xA;Hello world&#xA;</xsl:text>
 </xsl:template>

 <xsl:template match="@*|node()" mode="pass2">
  <xsl:call-template name="identity"/>
 </xsl:template>
</xsl:stylesheet>
<example>
    <content>Lorem ipsum</content>
    <content><replace /></content>
</example>
<example>
   <wrapper>
Hello world
Lorem ipsum</wrapper>
   <wrapper>
Hello world

Hello world
</wrapper>
</example>

你好,世界
乱数假文
你好,世界
你好,世界
注意事项

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common" exclude-result-prefixes="ext">

 <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="/">
  <xsl:variable name="vrtfPass1">
    <xsl:apply-templates/>
  </xsl:variable>

  <xsl:variable name="vPass1" select="ext:node-set($vrtfPass1)/*"/>

  <xsl:apply-templates select="$vPass1" mode="pass2"/>
 </xsl:template>

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

 <xsl:template match="replace">
  <xsl:text>&#xA;Hello world&#xA;</xsl:text>
 </xsl:template>

 <xsl:template match="@*|node()" mode="pass2">
  <xsl:call-template name="identity"/>
 </xsl:template>
</xsl:stylesheet>
<example>
    <content>Lorem ipsum</content>
    <content><replace /></content>
</example>
<example>
   <wrapper>
Hello world
Lorem ipsum</wrapper>
   <wrapper>
Hello world

Hello world
</wrapper>
</example>
在XSLT1.0中,应用模板的结果是臭名昭著的RTF类型(结果树片段),根据定义,除了使用
xsl:copy of
和标准字符串函数外,无法进一步访问和处理模板

这就是为什么几乎每个XSLT 1.0处理器都提供一个特定于供应商的扩展函数
xxx:node-set()
,该函数接受RTF并将其转换为“常规”树,可以使用任何XPath表达式访问其子代。此处,
xxx
前缀必须绑定到供应商指定的命名空间uri

EXSLT
ext:node-set()
由大多数XSLT处理器实现,因此它的使用保证了不同XSLT处理器之间的可移植性

有关附加的多过程转换示例,请参见以下内容:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common" exclude-result-prefixes="ext">

 <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="/">
  <xsl:variable name="vrtfPass1">
    <xsl:apply-templates/>
  </xsl:variable>

  <xsl:variable name="vPass1" select="ext:node-set($vrtfPass1)/*"/>

  <xsl:apply-templates select="$vPass1" mode="pass2"/>
 </xsl:template>

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

 <xsl:template match="replace">
  <xsl:text>&#xA;Hello world&#xA;</xsl:text>
 </xsl:template>

 <xsl:template match="@*|node()" mode="pass2">
  <xsl:call-template name="identity"/>
 </xsl:template>
</xsl:stylesheet>
<example>
    <content>Lorem ipsum</content>
    <content><replace /></content>
</example>
<example>
   <wrapper>
Hello world
Lorem ipsum</wrapper>
   <wrapper>
Hello world

Hello world
</wrapper>
</example>

而这

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common" exclude-result-prefixes="ext">

 <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="/">
  <xsl:variable name="vrtfPass1">
    <xsl:apply-templates/>
  </xsl:variable>

  <xsl:variable name="vPass1" select="ext:node-set($vrtfPass1)/*"/>

  <xsl:apply-templates select="$vPass1" mode="pass2"/>
 </xsl:template>

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

 <xsl:template match="replace">
  <xsl:text>&#xA;Hello world&#xA;</xsl:text>
 </xsl:template>

 <xsl:template match="@*|node()" mode="pass2">
  <xsl:call-template name="identity"/>
 </xsl:template>
</xsl:stylesheet>
<example>
    <content>Lorem ipsum</content>
    <content><replace /></content>
</example>
<example>
   <wrapper>
Hello world
Lorem ipsum</wrapper>
   <wrapper>
Hello world

Hello world
</wrapper>
</example>

这是一个两次转换,生成所需的结果

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common" exclude-result-prefixes="ext">

 <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="/">
  <xsl:variable name="vrtfPass1">
    <xsl:apply-templates/>
  </xsl:variable>

  <xsl:variable name="vPass1" select="ext:node-set($vrtfPass1)/*"/>

  <xsl:apply-templates select="$vPass1" mode="pass2"/>
 </xsl:template>

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

 <xsl:template match="replace">
  <xsl:text>&#xA;Hello world&#xA;</xsl:text>
 </xsl:template>

 <xsl:template match="@*|node()" mode="pass2">
  <xsl:call-template name="identity"/>
 </xsl:template>
</xsl:stylesheet>
<example>
    <content>Lorem ipsum</content>
    <content><replace /></content>
</example>
<example>
   <wrapper>
Hello world
Lorem ipsum</wrapper>
   <wrapper>
Hello world

Hello world
</wrapper>
</example>


;世界你好
;
应用于提供的XML文档时

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common" exclude-result-prefixes="ext">

 <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="/">
  <xsl:variable name="vrtfPass1">
    <xsl:apply-templates/>
  </xsl:variable>

  <xsl:variable name="vPass1" select="ext:node-set($vrtfPass1)/*"/>

  <xsl:apply-templates select="$vPass1" mode="pass2"/>
 </xsl:template>

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

 <xsl:template match="replace">
  <xsl:text>&#xA;Hello world&#xA;</xsl:text>
 </xsl:template>

 <xsl:template match="@*|node()" mode="pass2">
  <xsl:call-template name="identity"/>
 </xsl:template>
</xsl:stylesheet>
<example>
    <content>Lorem ipsum</content>
    <content><replace /></content>
</example>
<example>
   <wrapper>
Hello world
Lorem ipsum</wrapper>
   <wrapper>
Hello world

Hello world
</wrapper>
</example>

乱数假文
生成所需的正确结果

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common" exclude-result-prefixes="ext">

 <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="/">
  <xsl:variable name="vrtfPass1">
    <xsl:apply-templates/>
  </xsl:variable>

  <xsl:variable name="vPass1" select="ext:node-set($vrtfPass1)/*"/>

  <xsl:apply-templates select="$vPass1" mode="pass2"/>
 </xsl:template>

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

 <xsl:template match="replace">
  <xsl:text>&#xA;Hello world&#xA;</xsl:text>
 </xsl:template>

 <xsl:template match="@*|node()" mode="pass2">
  <xsl:call-template name="identity"/>
 </xsl:template>
</xsl:stylesheet>
<example>
    <content>Lorem ipsum</content>
    <content><replace /></content>
</example>
<example>
   <wrapper>
Hello world
Lorem ipsum</wrapper>
   <wrapper>
Hello world

Hello world
</wrapper>
</example>

你好,世界
乱数假文
你好,世界
你好,世界
注意事项

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common" exclude-result-prefixes="ext">

 <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="/">
  <xsl:variable name="vrtfPass1">
    <xsl:apply-templates/>
  </xsl:variable>

  <xsl:variable name="vPass1" select="ext:node-set($vrtfPass1)/*"/>

  <xsl:apply-templates select="$vPass1" mode="pass2"/>
 </xsl:template>

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

 <xsl:template match="replace">
  <xsl:text>&#xA;Hello world&#xA;</xsl:text>
 </xsl:template>

 <xsl:template match="@*|node()" mode="pass2">
  <xsl:call-template name="identity"/>
 </xsl:template>
</xsl:stylesheet>
<example>
    <content>Lorem ipsum</content>
    <content><replace /></content>
</example>
<example>
   <wrapper>
Hello world
Lorem ipsum</wrapper>
   <wrapper>
Hello world

Hello world
</wrapper>
</example>
在XSLT1.0中,应用模板的结果是臭名昭著的RTF类型(结果树片段),根据定义,除了使用
xsl:copy of
和标准字符串函数外,无法进一步访问和处理模板

这就是为什么几乎每个XSLT 1.0处理器都提供一个特定于供应商的扩展函数
xxx:node-set()
,该函数接受RTF并将其转换为“常规”树,可以使用任何XPath表达式访问其子代。此处,
xxx
前缀必须绑定到供应商指定的命名空间uri

EXSLT
ext:node-set()
由大多数XSLT处理器实现,因此它的使用保证了不同XSLT处理器之间的可移植性

有关附加的多过程转换示例,请参见以下内容:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common" exclude-result-prefixes="ext">

 <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="/">
  <xsl:variable name="vrtfPass1">
    <xsl:apply-templates/>
  </xsl:variable>

  <xsl:variable name="vPass1" select="ext:node-set($vrtfPass1)/*"/>

  <xsl:apply-templates select="$vPass1" mode="pass2"/>
 </xsl:template>

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

 <xsl:template match="replace">
  <xsl:text>&#xA;Hello world&#xA;</xsl:text>
 </xsl:template>

 <xsl:template match="@*|node()" mode="pass2">
  <xsl:call-template name="identity"/>
 </xsl:template>
</xsl:stylesheet>
<example>
    <content>Lorem ipsum</content>
    <content><replace /></content>
</example>
<example>
   <wrapper>
Hello world
Lorem ipsum</wrapper>
   <wrapper>
Hello world

Hello world
</wrapper>
</example>

而这

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common" exclude-result-prefixes="ext">

 <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="/">
  <xsl:variable name="vrtfPass1">
    <xsl:apply-templates/>
  </xsl:variable>

  <xsl:variable name="vPass1" select="ext:node-set($vrtfPass1)/*"/>

  <xsl:apply-templates select="$vPass1" mode="pass2"/>
 </xsl:template>

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

 <xsl:template match="replace">
  <xsl:text>&#xA;Hello world&#xA;</xsl:text>
 </xsl:template>

 <xsl:template match="@*|node()" mode="pass2">
  <xsl:call-template name="identity"/>
 </xsl:template>
</xsl:stylesheet>
<example>
    <content>Lorem ipsum</content>
    <content><replace /></content>
</example>
<example>
   <wrapper>
Hello world
Lorem ipsum</wrapper>
   <wrapper>
Hello world

Hello world
</wrapper>
</example>

这并不是在所有情况下都有效,但有一种非常简单的方法可以实现你的要求。您所需要做的就是为
replace
模板指定一个名称,并使用
xsl:calltemplate
调用它。这只需要对现有样式表进行几个小的更改:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform 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="content">
        <wrapper>
            <xsl:call-template name="replace"/>
            <xsl:apply-templates select="@*|node()" />
        </wrapper>
    </xsl:template>

    <xsl:template match="replace" name="replace">
        Hello world
    </xsl:template>
</xsl:transform>

你好,世界

并非在所有情况下都有效,但有一种非常简单的方法可以实现您的要求。您所需要做的就是为
replace
模板指定一个名称,并使用
xsl:calltemplate
调用它。这只需要对现有样式表进行几个小的更改:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform 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="content">
        <wrapper>
            <xsl:call-template name="replace"/>
            <xsl:apply-templates select="@*|node()" />
        </wrapper>
    </xsl:template>

    <xsl:template match="replace" name="replace">
        Hello world
    </xsl:template>
</xsl:transform>

你好,世界

根据其他答案的输入,这里是我解决问题的方法。考虑作为一个更合适的例子输入:

<?xml version="1.0" encoding="utf-8" ?>
<example>
    <a />
    <b />
    <c />
</example>

元素
在我的原始示例中的使用方式与
类似,但如转换中所示,它们的模板都包含对它们的进一步引用:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ext="http://exslt.org/common"
exclude-result-prefixes="ext">

    <xsl:template match="@*|node()">
        <xsl:variable name="this">
            <xsl:apply-templates select="." mode="normal" />
        </xsl:variable>
        <xsl:apply-templates select="ext:node-set($this)" mode="normal" />
    </xsl:template>

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

    <xsl:template match="a" mode="normal">a</xsl:template>

    <xsl:template match="b" mode="normal">
        <B>b <a /></B>
    </xsl:template>

    <xsl:template match="c" mode="normal">
        <C>c <b /></C>
    </xsl:template>
</xsl:transform>

A.
B
C
当应用于示例输入时,此转换生成我想要的结果:

<?xml version="1.0"?>
<example>
    a
    <B>b a</B>
    <C>c <B>b a</B></C>
</example>

A.
b a
c b a
显然,所有递归引用都已解决。虽然它通过一些更复杂的例子进行了测试,但我不确定它是否能在所有情况下都起作用

这背后的想法如下:前两个模板用于复制。带有
mode=“normal”
的是一个普通的身份转换,而没有的是递归。模式用于防止递归模板中出现无限循环


请让我知道,你对此有何看法,是否有明显的缺陷

根据其他答案的输入,这里是我解决问题的方法。考虑作为一个更合适的例子输入:

<?xml version="1.0" encoding="utf-8" ?>
<example>
    <a />
    <b />
    <c />
</example>

元素
在我的原始示例中的使用方式与
类似,但如转换中所示,它们的模板都包含对它们的进一步引用:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ext="http://exslt.org/common"
exclude-result-prefixes="ext">

    <xsl:template match="@*|node()">
        <xsl:variable name="this">
            <xsl:apply-templates select="." mode="normal" />
        </xsl:variable>
        <xsl:apply-templates select="ext:node-set($this)" mode="normal" />
    </xsl:template>

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

    <xsl:template match="a" mode="normal">a</xsl:template>

    <xsl:template match="b" mode="normal">
        <B>b <a /></B>
    </xsl:template>

    <xsl:template match="c" mode="normal">
        <C>c <b /></C>
    </xsl:template>
</xsl:transform>