2015-04-23 74 views
0

我習慣於在我的XSLT中具有基於輸入中節點樹的條件。但我想根據輸出結果來做。有什麼辦法嗎?基於輸出樹的XSLT條件

下面是一個例子。

輸入:

<top> 
    <a> 
     <z> 
      <item> 
       <id>4</id> 
      </item> 
      <item> 
       <id>5</id> 
      </item> 
     </z> 
    </a> 
</top> 

希望的輸出:

<thing> 
    <upper> 
     <a> 
      <z> 
       <item> 
        <id>upper-4</id> 
       </item> 
       <item> 
        <id>upper-5</id> 
       </item> 
      </z> 
     </a> 
    </upper> 
    <lower> 
     <a> 
      <z> 
       <item> 
        <id>lower-4</id> 
       </item> 
       <item> 
        <id>lower-5</id> 
       </item> 
      </z> 
     </a> 
    </lower> 
</thing> 

注意,樹基本上由一個向下複製,唯一的變化是在id節點的值已被根據是否修改我們在upperlower樹中。

我現在的XSLT:

<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema"> 

    <xsl:template match="top"> 
     <thing> 
      <upper> 
       <xsl:apply-templates /> 
      </upper> 
      <lower> 
       <xsl:apply-templates /> 
      </lower> 
     </thing> 
    </xsl:template> 

    <xsl:template match="id"> 
     <!-- I want to prepend this with "upper" or "lower" depending which block we're in --> 
     <xsl:value-of select="text()" /> 
    </xsl:template> 

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

這是一個簡單的例子,也有az之間的樹很多節點,以及節點item可以出現在a下的不同深度。

最初我的狀態看起來像ancestor::upper,但顯然不起作用,因爲upper在輸出中,而不是輸入。

我也考慮過試圖傳遞一個參數來說,如果我們在upperlower,但這意味着更新每一個模板(包括身份模板)有一個參數,也傳遞給它它調用的任何模板。如果可能,我真的想避免這種情況。

所以,如果有一種方法可以將變量傳遞給被調用的模板而不必聲明變量,那就行了。或者,如果我可以編寫一個條件來查看調用我們的模板或者我們上面樹中的輸出,那就行得通了。或者還有其他方法可以做到這一點嗎?

請注意,我使用的是撒克遜處理器,所以我可以使用特定的功能(例如,如果有幫助,我可以致電給某些java)。

謝謝。

+0

您的代碼說'版本= 「2.0」'但Xalan的是一個XSLT 1.0處理器。如果您切換到Saxon 9並真正使用XSLT 2.0,那麼您可以使用隧道參數來避免必須使用每個apply-templates傳遞參數。除此之外,我認爲參數是正確的方法。 –

+0

@MartinHonnen對不起,我的意思是撒克遜...(我目前使用的是版本9.1.0.8)我會研究隧道參數,但我之前沒有遇到過。 – stripybadger

回答

0

下面是使用的隧道參數與XSLT 2.0的溶液:

<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    exclude-result-prefixes="xs"> 

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

    <xsl:template match="top"> 
     <thing> 
      <upper> 
       <xsl:apply-templates> 
        <xsl:with-param name="tree-id" tunnel="yes" select="'upper-'"/> 
       </xsl:apply-templates> 
      </upper> 
      <lower> 
       <xsl:apply-templates> 
        <xsl:with-param name="tree-id" tunnel="yes" select="'lower-'"/> 
       </xsl:apply-templates> 
      </lower> 
     </thing> 
    </xsl:template> 

    <xsl:template match="id"> 
     <xsl:param name="tree-id" tunnel="yes"/> 
     <xsl:copy> 
      <!-- I want to prepend this with "upper" or "lower" depending which block we're in --> 
      <xsl:value-of select="concat($tree-id, .)" /> 
     </xsl:copy> 
    </xsl:template> 


</xsl:stylesheet> 
+0

完美 - 我之前沒有遇到隧道參數,謝謝。 – stripybadger