Навигация и сортировка XML внутри xsl: variable с использованием XSLT 2.0 - PullRequest
1 голос
/ 20 октября 2010

XML внутри переменной 'formslist' создается с использованием apply-templates.Этот фрагмент взят из таблицы стилей 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

Ответы [ 2 ]

0 голосов
/ 20 октября 2010
<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-документу (не используется), получается требуемый, правильный результат :

<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 голосов
/ 20 октября 2010

Это потому, что $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>
...