2011-01-21 43 views
4

我有任何元素與<var>孩子匹配的XSL模板:xslt:如何在處理過程中將兩個模板應用於同一個節點?

<xsl:template match="*[var]"> 
    <xsl:copy > 
     <xsl:attribute name="editable"> 
      <xsl:for-each select="var[@attr]"> 
       <xsl:value-of 
           select="concat(@attr, 
              substring(' ', 
                 1 div (position()!=last())))"/> 
      </xsl:for-each> 
     </xsl:attribute> 
     <xsl:attribute name="constraints"> 
      <xsl:for-each select="var[@ok]"> 
       <xsl:value-of 
           select="concat(@attr,':',@ok, 
              substring(';', 
                 1 div (position()!=last())))"/> 
      </xsl:for-each> 
     </xsl:attribute> 
     <!-- if this is an <a> then we have to put the stuff inside it inside it --> 
     <xsl:apply-templates select="@*" /> 
     <xsl:apply-templates /> 
    </xsl:copy> 
</xsl:template> 

它加到了attr S中的變種元素融入母公司的editable屬性;和ok s分成constraint s。

然後,我有任何<field>元素相匹配的模板:

<xsl:template match="field"> 
    <span> 
     <xsl:attribute name="field"> 
      <xsl:choose> 
       <xsl:when test="boolean(@name)"> 
        <xsl:value-of select="./@name"/> 
       </xsl:when> 
       <xsl:otherwise> 
        <xsl:text>true</xsl:text> 
       </xsl:otherwise> 
      </xsl:choose> 
     </xsl:attribute> 
     <xsl:apply-templates /> 
    </span> 
</xsl:template> 

這僅僅是一個名稱相同的字段轉換爲<span field="name">,如果字段有一個,否則「真」。

問題我現在是,*[var]匹配一個字段,如果該字段有一個<var>作爲孩子。但我想要發生的是*[var]匹配第一個,然後field以匹配以及,但之後

目前,隨着

<field name="field1"> 
    <var attr="class" ok="small,smaller" /> 
    Text 
</field> 

輸入我得到

<field name="field1" editable="class" constraints="class:small,smaller"> 
    Text 
</field> 

但我想

<span field="field1" editable="class" constraints="class:small,smaller"> 
    Text 
</span> 

我發現SO一些答案這樣做兩遍,但我不知道這是正確的答案,也不知道如何實現我找到的答案。我應該如何處理這個問題,如果有簡單的答案,它是什麼? :)

TIA Altreus

回答

0
<xsl:template match="var"> 
    <xsl:attribute name="editable"> 
      <xsl:value-of select="@attr"/> 
    </xsl:attribute> 
    <xsl:attribute name="constraints"> 
      <xsl:value-of select="concat(@attr,':',@ok)"/> 
    </xsl:attribute> 
    <xsl:apply-templates /> 
</xsl:template> 
<xsl:template match="field"> 
    <span> 
    <xsl:attribute name="field"> 
     <xsl:choose> 
      <xsl:when test="@name"> 
       <xsl:value-of select="@name"/> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:text>true</xsl:text> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:attribute> 
    <xsl:apply-templates /> 
    </span> 
</xsl:template> 
+0

像這樣移動var元素是我考慮的事情;但我不確定我將如何執行第二個連接 - 帶分號的連接。我害怕我沒有完全理解原作 - 它只是工作 - 而且我還沒有花時間坐下來解決它:o!也許在這個項目迭代結束時...... – Altreus 2011-01-27 16:24:29

2

這個樣式表:

<xsl:stylesheet 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="*[var]"> 
     <xsl:copy> 
      <xsl:call-template name="makeVarAttribute"/> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 
    <xsl:template match="field" priority="1"> 
     <span field="{concat(@name, 
          substring('true', 
             1 div not(@name) 
            ) 
          )}"> 
      <xsl:apply-templates select="." mode="makeVarAttribute"/> 
      <xsl:apply-templates /> 
     </span> 
    </xsl:template> 
    <xsl:template match="var"/> 
    <xsl:template match="node()" mode="makeVarAttribute"/> 
    <xsl:template match="*[var]" 
        name="makeVarAttribute" 
        mode="makeVarAttribute"> 
     <xsl:attribute name="editable"> 
      <xsl:for-each select="var[@attr]"> 
       <xsl:value-of 
         select="concat(@attr, 
             substring(' ', 
                1 div (position()!=last()) 
               ) 
             )"/> 
      </xsl:for-each> 
     </xsl:attribute> 
     <xsl:attribute name="constraints"> 
      <xsl:for-each select="var[@ok]"> 
       <xsl:value-of 
         select="concat(@attr,':',@ok, 
             substring(';', 
                1 div (position()!=last()) 
               ) 
             )"/> 
      </xsl:for-each> 
     </xsl:attribute> 
    </xsl:template> 
</xsl:stylesheet> 

輸出:

<span field="field1" editable="class" constraints="class:small,smaller"> 
    Text 
</span> 

注意:使用@priority因爲*[var]圖案均具有較高的默認優先級高於field,將常用內容模板封裝在一個已命名的模板中,使用@mode進行兩次節點處理(首先是span轉換,然後是屬性填充如果存在var子)。

編輯:我沒有看到。此XSLT樣式表2.0

<xsl:stylesheet version="2.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="*[var]"> 
     <xsl:copy> 
      <xsl:call-template name="makeVarAttribute"/> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 
    <xsl:template match="field" priority="1"> 
     <span field="{(@name,'true')[1]}"> 
      <xsl:apply-templates select="." mode="makeVarAttribute"/> 
      <xsl:apply-templates /> 
     </span> 
    </xsl:template> 
    <xsl:template match="var"/> 
    <xsl:template match="node()" mode="makeVarAttribute"/> 
    <xsl:template match="*[var]" 
        name="makeVarAttribute" 
        mode="makeVarAttribute"> 
     <xsl:attribute name="editable" select="var/@attr"/> 
     <xsl:attribute name="constraints" 
         select="var[@ok]/concat(@attr,':',@ok)" 
         separator=";"/> 
    </xsl:template> 
</xsl:stylesheet> 

:序列處理中,在表達功能作爲最後一個步驟,@separator

7

如果要將兩個模板應用於同一個節點,可以使用匹配節點的最高優先級規則中的xsl:next-match:,您可以調用xs:next-match來調用次最高優先級, 等等。當然,您可以使用xsl:template的優先級屬性來「手動」調整優先級。

這裏還有其他幾種可能性:

(一)它從一個快速瀏覽的「VAR」元素的處理可以在VaR的元素相匹配,而不是* [模板來完成我看來,變種],在這種情況下,它可以通過XSL調用:應用模板以通常的方式

(b)所述第一模板可使用應用模板在特殊模式下

(c)中調用第二的第一個模板可以在變量中構建一個臨時元素,然後將模板應用於該模板。

+0

+1作爲詳盡的答案。 – 2011-01-21 19:00:03

相關問題