2010-10-19 1 views
1

XML в переменной «formlist» создается с использованием шаблонов apply-templates. Этот фрагмент из таблицы стилей 2.0.Навигация и сортировка XML в xsl: переменная с использованием XSLT 2.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> 

XML-выходы в порядке, но это не отсортирован по print_seq

+0

Хороший вопрос, +1. См. Мой ответ для подробного обсуждения проблем в предоставленном XSLT-коде и для краткого и простого решения. :) –

ответ

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:

<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>