2015-10-15 52 views
0

我正在修改一些XSL,这些XSL已经附带了一些相对于当前上下文节点输出数据的模板。我想用不同的上下文调用相同的模板,因此我不必通过传递其他参数来更改现有的模板。使用不同的上下文调用xsl模板

例如XML:

<anyRoot> 
<level1> 
    <a>xxxxxx</a> 
    <b>yyyyyy</b> 
    <level2> 
     <a>aaaaa</a> 
     <b>bbbbbb</b> 
     <c>cccccc</c> 
     <d>dddddd</d> 
    </level2> 
</level1> 
<level1> 
    <a>zzzzzz</a> 
    <b>jjjjjj</b> 
    <level2> 
     <a>nnnnn</a> 
     <b>bbbbbb</b> 
     <c>cccccc</c> 
     <d>dddddd</d> 
    </level2> 
</level1> 
</anyRoot> 

理论XSL。请注意,“上下文=”属性是无效的,但我把它放在那里来解释我的想法:

... 
<xsl:for-each select="/anyRoot/level1/level2"> 
    <xsl:call-template name="testTmplate"/> 
    <xsl:call-template name="testTmplate" context=".."/> <!-- passing parent of level2--> 
</xsl:for-each> 
... 

<xsl:template name="testTmplate"> 
    <xsl:value-of select="./a"/> 
</xsl:template> 

这是我希望看到的输出:

aaaaa 
xxxxxxx 

nnnnnnn 
zzzzzzz 
+0

嗨,你是通过尝试重用模板代码做正确的事情!一些意见: – kjm

+0

我期望的第一个呼叫模板的工作。第二个将不起作用,但如果你谷歌的祖先轴,你应该找到答案的方式。请尝试这些更改,看看它是如何发生的。 – kjm

+0

谢谢蒂姆。你的回答游戏是一个非常重要的线索,所以我最终为第二个模板调用添加了一个新模板(从父类中抽取数据的模板)。这个新模板充当包装模板来调用现有的模板。见下面的答案。 –

回答

0

谢谢Tim。你的回答游戏是一个非常重要的线索,所以我最终为第二个模板调用添加了一个新模板(从父类中抽取数据的模板)。这个新模板充当包装模板来调用现有的模板。见下面的答案。

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

    <xsl:template match="/"> 
     <xsl:for-each select="/anyRoot/level1/level2"> 
      <xsl:call-template name="testTemplate" /> 
      <xsl:apply-templates select=".." mode="testTemplateWrapper" /> 
     </xsl:for-each> 
    </xsl:template> 

    <xsl:template name="testTemplate"> 
     <xsl:value-of select="a"/> 
     <xsl:text>&#10;</xsl:text> 
    </xsl:template> 

    <xsl:template match="level1" mode="testTemplateWrapper"> 
     <xsl:call-template name="testTemplate" /> 
    </xsl:template> 

</xsl:stylesheet> 
2

如果你想改变背景,你应该真的在这里使用xsl:apply-templates,并有一个匹配的模板。

例如

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
<xsl:output method="text" /> 

<xsl:template match="/"> 
<xsl:for-each select="/anyRoot/level1/level2"> 
    <xsl:apply-templates select="a" /> 
    <xsl:apply-templates select="../a" /> 
</xsl:for-each> 
</xsl:template> 

<xsl:template match="a"> 
    <xsl:value-of select="."/> 
    <xsl:text>&#10;</xsl:text> 
</xsl:template> 
</xsl:stylesheet> 

但是,如果在您的实际XSLT另一个模板,它也符合“一”的元素,你可以区分你需要通过使用mode属性的一个,像这样:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
<xsl:output method="text" /> 

<xsl:template match="/"> 
<xsl:for-each select="/anyRoot/level1/level2"> 
    <xsl:apply-templates select="a" mode="testTmplate" /> 
    <xsl:apply-templates select="../a" mode="testTmplate" /> 
</xsl:for-each> 
</xsl:template> 

<xsl:template match="a" mode="testTmplate"> 
    <xsl:value-of select="."/> 
    <xsl:text>&#10;</xsl:text> 
</xsl:template> 
</xsl:stylesheet> 

编辑:如果你真的想调用一个现有的名称模板这个方法,只需从匹配的模板调用它。在原始./a尝试......

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
<xsl:output method="text" /> 

<xsl:template match="/"> 
<xsl:for-each select="/anyRoot/level1/level2"> 
    <xsl:call-template name="testTmplate"/> 
    <xsl:apply-templates select=".." mode="testTmplate" /> 
</xsl:for-each> 
</xsl:template> 

<xsl:template match="*" mode="testTmplate"> 
    <xsl:call-template name="testTmplate"/> 
</xsl:template> 

<xsl:template name="testTmplate"> 
    <xsl:value-of select="a"/> 
    <xsl:text>&#10;</xsl:text> 
</xsl:template> 
</xsl:stylesheet> 
+0

在我尝试解析模板(还有更多模板)的情况下,它是按名称定义的,它不使用“匹配”,我不能使用“选择”来调用命名模板。有没有解决这个限制的方法? –

+0

我认为你的解决方案是围绕XSL限制的最佳工作。设计XSL的人应该认真考虑添加一个新的“context =”属性来避免所有这些“修复”。 –

+0

我修改了我的答案,以显示如果您真的想这样做,仍然可以使用您的命名模板。 –

0

./是多余的,和@恬-C说,你会使用xsl:apply-templates可能会更好。但是,如果你不想惹太多与现有的xsl:call-template和命名模板的设置,你可以添加一个参数(比如,$context),默认上下文节点,然后覆盖,按照需要:

<xsl:for-each select="/anyRoot/level1/level2"> 
    <xsl:call-template name="testTmplate"/> 
    <xsl:call-template name="testTmplate"> 
     <xsl:param name="context" select=".."/> <!-- passing parent of level2--> 
    </xsl:call-template> 
</xsl:for-each> 
... 

<xsl:template name="testTmplate"> 
    <xsl:param name="context" select="."/> 
    <xsl:value-of select="$context/a"/> 
</xsl:template> 

因此./a变得更有用,因为$context/a

+0

谢谢。问题是,如果我为这个模板引入一个参数,我必须将参数的引入级联到从这个模板中调用的所有其他模板,并且在真正的XSL程序中有很多。 –

0

错误的方式在下面!请参阅Tim的正确答案。但是,假设您已命名模板,则无法更改或不会更改,而您希望重新使用它们,请参阅下文。当然,根据您当前的代码,您可以将参数添加到模板中,或者更好地使用具有模式的未命名模板。

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output method="text" /> 

    <xsl:template match="/"> 
    <xsl:for-each select="/anyRoot/level1/level2"> 
     <xsl:call-template name="testTmplate"/> 
    </xsl:for-each> 
    <xsl:for-each select="/anyRoot/level1"> 
     <xsl:call-template name="testTmplate"/> 
    </xsl:for-each> 
    </xsl:template> 

    <xsl:template name="testTmplate"> 
    <xsl:value-of select="./a"/> 
    <xsl:text>&#10;</xsl:text> 
    </xsl:template> 
</xsl:stylesheet> 
0

,不改变现有的命名模板将使用xsl:for-each改变上下文的一种方式:

<xsl:for-each select="/anyRoot/level1/level2"> 
    <xsl:call-template name="testTmplate"/> 
    <xsl:for-each select=".."> <!-- parent of level2 --> 
     <xsl:call-template name="testTmplate"/> 
    </xsl:for-each> 
</xsl:for-each> 

我毫不犹豫地推荐这个,因为,海事组织,它不是为可读,但乱扔垃圾$context的很多模板可能最终也不太可读。