2010-04-14 42 views
1

我想在xslt腳本中模擬一個標誌。這個想法是爲模板foo設置一個標誌(或者一個計數器變量,或者其他任何東西),以便它可以從模板欄訪問。 Bar不是從foo調用的,而是從一個共同的父模板中調用的(否則我會傳遞一個參數給它)。結構是這樣的:你可以在XSLT中模擬布爾標誌嗎?

<xsl:template match="bla"> 
    <xsl:apply-templates select="foo"/> <!-- depending on the contents of foo... --> 
    <xsl:apply-templates select="bar"/> <!-- ... different things should happen in bar --> 
</xsl:template> 

任何技巧,非常感謝。

+0

請提供更多信息。問題嚴重不足。 – 2010-04-14 21:50:04

回答

4

不是真的......至少不是你想要這樣做的意義。 XSLT中的變量是不可變的,一旦你給它們賦值,你不能改變它們,所以試圖多次調用foo來改變標誌的值是行不通的。 ,

<xsl:variable name="myFlag"><xsl:apply-templates select="foo" /></xsl:variable> 

<xsl:template match="bla"> 
     <xsl:apply-templates select="bar" /> <!-- Can use the value of $myFlag --. 
</xsl:template> 

如果模板富是建立在返回標誌的值,它會工作,但是如果:有一對夫婦的模式,你可以嘗試,這可能會完成你正在嘗試做的,例如該標誌的價值意味着隨着時間的推移而變化,唯一可以實現的方法是將調用foo納入條模板中。

<xsl:template match="bla"> 
    <xsl:apply-templates select="bar"> /> 
</xsl:template> 

<xsl:template match="bar"> 
    <xsl:variable name="flag"><xsl:apply-templates name="foo" /></xsl:variable> 

    <xsl:if test="$flag=1"> 

    </xsl:if> 
</xsl:template> 
1

有很多方法可以做到這一點。例如:

  • 您可以使用像xsl:if/xsl:choose這樣的條件結構。
  • 您可以使用變量來存儲從foo計算的任何內容,並將其作爲參數傳遞給bar上的apply-templates。

真正的XSLT方式是對子級來定義巴不同的模板 - 配合不同的foo的案件:

<xsl:template match="bar[../foo[@a='x']]"> 
    ... 
</xsl:template> 
<xsl:template match="bar[../foo[@a='y']]"> 
    ... 
</xsl:template> 
0

如果模板富應產生輸出,使用輸出爲標誌的任何解決方案將無法正常工作。在這種情況下,如果您使用的是基於Java的XSLT處理器(例如Saxon或Xalan),則可以使用可變的Java對象。

但請注意,這有它自己的困難。下面給出的轉換使用全局標誌,可能不足以滿足所有用例。我想在bla模板中實例化標誌並將其作爲參數傳遞給foo和bar,但是我無法在Xalan中使用它。另請注意,我在xsl:value-of中調用了Java設置器,因爲否則該調用可能會被優化掉(請參閱Cannot access updated Java object from Saxon XSLT processor)。

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:myflag="java:mypackage.MyFlag"> 

<xsl:variable name="foo-flag" select="myflag:new()" /> 

<xsl:template match="bla"> 
    <xsl:apply-templates select="foo"/> <!-- depending on the contents of foo... --> 
    <xsl:apply-templates select="bar"/> <!-- ... different things should happen in bar --> 
</xsl:template> 

<xsl:template match="foo"> 
    <xsl:choose> 
    <xsl:when ...> 
     <xsl:value-of select="myflag:set($foo-flag, true())" /> 
     ... 
    </xsl:when> 
    <xsl:otherwise> 
     <xsl:value-of select="myflag:set($foo-flag, false())" /> 
     ... 
    </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

<xsl:template match="bar"> 
    <xsl:choose> 
    <xsl:when test="myflag:get($foo-flag)"> 
     ... 
    </xsl:when> 
    <xsl:otherwise> 
     ... 
    </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

</xsl:transform> 

MyFlag類的最基本版本只是一個可變的布爾包裝器。

public class MyFlag { 
private boolean flag; 
public void set(boolean flag){ 
    this.flag = flag; 
} 
public boolean get(){ return flag; } 
} 
0

這使用您在問題中提到的方法:傳遞一個參數,從foo到bar。注意:這假定每個bla下面都有一個foo,否則每個bar元素將不會調用或不超過一次調用條形模板。

<xsl:template match="bla"> 
    <xsl:apply-templates select="foo" /> 
</xsl:template> 

<xsl:template match="foo"> 
    ...  
    <xsl:apply-templates select="../bar"> 
    <xsl:with-param name="flag" select="..." /> 
    </xsl:apply-templates /> 
</xsl:template>