2010-10-19 18 views
1

'formslist'變量中的XML是使用apply-templates創建的。這段代碼來自2.0樣式表。使用XSLT 2.0在xsl:variable中導航和排序XML

<xsl:variable name="formlist"> 
    <forms> 
    <FORM form_name="form1" print_seq="1200"/> 
    <FORM form_name="form2" print_seq="1500"/> 
    <FORM form_name="form3" print_seq="9000"/> 
    <FORM form_name="form4" print_seq="5500"/> 
    </forms> 
</xsl:variable> 

    <xsl:for-each select="$formslist/*"> 
    <xsl:sort select="FORM/@print_seq"/> 
    <xsl:copy-of select="."/> 
    </xsl:for-each> 

的XML輸出確定,但它不是由print_seq

+0

好問題,+1。請參閱我的答案,詳細討論提供的XSLT代碼中的問題以及簡短易用的解決方案。 :) – 2010-10-19 22:59:03

回答

0
<xsl:variable name="formlist">  
    <forms>  
    <FORM form_name="form1" print_seq="1200"/>  
    <FORM form_name="form2" print_seq="1500"/>  
    <FORM form_name="form3" print_seq="9000"/>  
    <FORM form_name="form4" print_seq="5500"/>  
    </forms>  
</xsl:variable>  

    <xsl:for-each select="$formslist/*">  
    <xsl:sort select="FORM/@print_seq"/>  
    <xsl:copy-of select="."/>  
    </xsl:for-each> 

這段代碼的問題:

  1. formlist變量沒有指定類型,默認情況下它的類型是document-node()這意味着$formlist/*選擇單個頂部元素forms,並排序單個元素導致完全這個元素(不變)。如果變量的類型被指定爲as="element()",則可以避免該問題。

  2. 即便上述問題已經得到了解決,指定的排序關鍵字FORM/@print_seq是不正確 - 一個FORM元素沒有一個FORM孩子。正確的排序鍵只是:@print_seq

  3. 即使上述前兩個問題不存在,排序依然不正確,因爲排序鍵類型被視爲字符串而不是數字。正確<xsl:sort>指令需要有data-type="number"指定或排序關鍵字本身應該已經被指定爲xs:integer(@print_seq)

解決方案

只需使用

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes"/> 

<xsl:variable name="formslist" as="element()"> 
    <forms> 
    <FORM form_name="form1" print_seq="1200"/> 
    <FORM form_name="form2" print_seq="1500"/> 
    <FORM form_name="form3" print_seq="9000"/> 
    <FORM form_name="form4" print_seq="5500"/> 
    </forms> 
</xsl:variable> 

    <xsl:template match="/"> 
    <xsl:element name="{name($formslist)}"> 
     <xsl:for-each select="$formslist/*"> 
     <xsl:sort select="@print_seq" data-type="number"/> 
     <xsl:copy-of select="."/> 
     </xsl:for-each> 
    </xsl:element> 
    </xsl:template> 
</xsl:stylesheet> 

當這轉換應用於任何XML文檔(未使用),正確的,正確的sult is

<forms> 
    <FORM form_name="form1" print_seq="1200"/> 
    <FORM form_name="form2" print_seq="1500"/> 
    <FORM form_name="form4" print_seq="5500"/> 
    <FORM form_name="form3" print_seq="9000"/> 
</forms> 
0

這是因爲$formslist/*選擇forms元素進行排序。

你可以聲明$ FORMLIST爲:

<xsl:variable name="formlist" as="element()"> 
    <forms> 
    <FORM form_name="form1" print_seq="1200"/> 
    <FORM form_name="form2" print_seq="1500"/> 
    <FORM form_name="form3" print_seq="9000"/> 
    <FORM form_name="form4" print_seq="5500"/> 
    </forms> 
</xsl:variable> 

但是你將失去在副本中forms元素。

其他解決方案將與排序的身份規則。這個樣式表:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:variable name="formlist"> 
     <forms> 
      <FORM form_name="form1" print_seq="1200"/> 
      <FORM form_name="form2" print_seq="1500"/> 
      <FORM form_name="form3" print_seq="9000"/> 
      <FORM form_name="form4" print_seq="5500"/> 
     </forms> 
    </xsl:variable> 
    <xsl:template match="/"> 
     <xsl:apply-templates select="$formlist" mode="copy"/> 
    </xsl:template> 
    <xsl:template match="node()|@*" mode="copy"> 
     <xsl:copy> 
      <xsl:apply-templates select="node()|@*" mode="copy"> 
       <xsl:sort select="self::FORM/@print_seq"/> 
      </xsl:apply-templates> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

輸出:

<forms> 
    <FORM form_name="form1" print_seq="1200"/> 
    <FORM form_name="form2" print_seq="1500"/> 
    <FORM form_name="form4" print_seq="5500"/> 
    <FORM form_name="form3" print_seq="9000"/> 
</forms>