2015-10-15 55 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的很多模板可能最終也不太可讀。