Можете ли вы определить пользовательские параметры сортировки, используя функцию в XSLT? - PullRequest
2 голосов
/ 17 октября 2011

Я бы хотел определить порядок строк, используемых в определенном элементе. Например, Старший Младший Второкурсник Первокурсник описал бы разумный порядок в классе.

Есть ли способ использования , который бы сортировал по порядку, указанному выше?

Заранее спасибо.

Ответы [ 2 ]

5 голосов
/ 17 октября 2011

Что вы могли бы сделать в вашем XSLT - это определить переменную для представления вашего пользовательского порядка, например

<xsl:variable name="inline-array">
   <class sort="1">Senior</class>
   <class sort="2">Junior</class>
   <class sort="3">Sophomore</class>
   <class sort="4">Freshman</class>
</xsl:variable>

Затем для доступа к этому «массиву» вы можете определить другую переменную для ссылки на сам документ XSLT:

<xsl:variable name="array" 
   select="document('')/*/xsl:variable[@name='inline-array']/*" />

Теперь это позволяет вам искать атрибут sort для данного имени класса при сортировке (где current () представляет текущий сортируемый узел)

<xsl:sort select="$array[. = current()/@class]/@sort" />

В качестве примера приведем полный XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>

   <xsl:variable name="inline-array">
      <class sort="1">Senior</class>
      <class sort="2">Junior</class>
      <class sort="3">Sophomore</class>
      <class sort="4">Freshman</class>
   </xsl:variable>

   <xsl:variable name="array" 
      select="document('')/*/xsl:variable[@name='inline-array']/*"/>

   <xsl:template match="/objects">
      <xsl:copy>
         <xsl:apply-templates select="object">
            <xsl:sort select="$array[. = current()/@class]/@sort" />
         </xsl:apply-templates>
      </xsl:copy>
   </xsl:template>

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

При применении этого к следующему образцу XML ...

<objects>
   <object id="2" name="Junior Jo" class="Junior" />
   <object id="1" name="Senior Sue" class="Senior" />
   <object id="4" name="Freshman Frank" class="Freshman" />
   <object id="3" name="Sophie Sophomore" class="Sophomore" />
</objects>

Возвращается следующее

<objects>
   <object id="1" name="Senior Sue" class="Senior"></object>
   <object id="2" name="Junior Jo" class="Junior"></object>
   <object id="3" name="Sophie Sophomore" class="Sophomore"></object>
   <object id="4" name="Freshman Frank" class="Freshman"></object>
</objects>
4 голосов
/ 18 октября 2011

Вы изучили пользовательские расширения сортировки Saxon?

Например,

<xsl:variable name="rules" select="'&lt; Freshman &lt; Sophomore
                                    &lt; Junior   &lt; Senior'" />

При этом используется формат RuleBasedCollator из класса Java с таким именем.

Чтобы использовать его в своем роде (использование полезного примера Тима С для ввода XML и таблицы стилей):

 <xsl:apply-templates select="object">
    <xsl:sort select="@class"
       collation="http://saxon.sf.net/collation?rules={encode-for-uri($rules)}"/>
 </xsl:apply-templates>

Это дает те же результаты, что и решение Тима С.(Протестировано с использованием Saxon PE 9.3.0.5.)

Это не функция xsl:, но она дает вам немного больше гибкости, чем массив, и, возможно, более лаконична.AFAICT нет способа создать пользовательское сопоставление, используя пользовательскую функцию XSLT.Поскольку вы не говорите, зачем вам нужен xsl:function, трудно предположить, какие альтернативы будут отвечать вашим потребностям.

Для полной гибкости, подобной xsl: function, вы можете определить свой собственный коллатер в Java;см. http://www.saxonica.com/documentation/extensibility/collation.xml о реализации интерфейса java.util.Comparator и указании компаратора в атрибуте class.

...