Как отсортировать по шестнадцатеричным в xslt? - PullRequest
6 голосов
/ 14 июня 2010

я пытаюсь отсортировать преобразованный вывод по элементу, который содержит шестнадцатеричное значение.

<code><xsl:sort select="Generation/Sirio/Code" data-type="number"/>

Значения представляют собой простой старый Hex: 00 01 02 ... 0A ... FF, но они сортируются следующим образом: 0A FF 00 01 02, что указывает на сбой метода сортировки, как толькозадействованы персонажи.

Как я могу обойти это?

Большое спасибо!

Ответы [ 2 ]

2 голосов
/ 14 июня 2010

Это преобразование :

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

    <xsl:variable name="vZeroes"
     select="'00000000000000000000000000000000000000'"/>

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

 <xsl:template match="/*">
  <xsl:copy>
    <xsl:apply-templates select="*">
       <xsl:sort select=
         "concat(substring($vZeroes,
                           1,
                           string-length($vZeroes)
                          -
                           string-length(@hexVal)
                           ),
                  translate(@hexVal,'abcdef','ABCDEF')
                 )
         "/>
    </xsl:apply-templates>
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

при применении к этому документу XML:

<t>
  <x hexVal="0A"/>
  <x hexVal="0327FE"/>
  <x hexVal="ff5240"/>
  <x hexVal="1BA402"/>
  <x hexVal="C3A214"/>
</t>

дает желаемый, правильный результат:

<t>
   <x hexVal="0A"/>
   <x hexVal="0327FE"/>
   <x hexVal="1BA402"/>
   <x hexVal="C3A214"/>
   <x hexVal="ff5240"/>
</t>

Подробности решения :

Единственное предположение, которое делает это решение, заключается в том, что максимальная длина шестнадцатеричных ключей сортировки ограничена (скажем, до 20). Затем мы используем строку нулей, длиннее этой максимальной длины. Переменная $vZeroes содержит эту строку нулей и используется для заполнения каждого ключа сортировки слева нулями, чтобы все ключи сортировки имели одинаковую длину.

1 голос
/ 14 июня 2010

Самое простое решение

Просто удалите data-type="number".

Ваш пример будет просто отлично сортироваться как текст (по умолчанию).В общем, простая сортировка как текст, вероятно, лучший подход .XSLT 1.0 не очень хорошо обрабатывает произвольные преобразования данных, и если вы попытаетесь использовать его как «общий» строковый процессор, вы получите большие, сложные и сложные в обслуживании преобразования.

Если вы делаете сортировку как текст, вам нужно убедиться, что все числа дополняются нулями слева до одинаковой длины.Все буквы должны быть в одном и том же случае (что в любом случае почти всегда верно, но может сломаться, если вы объедините данные из разных источников.) Обычно эти требования легко выполнить за пределами XSLT.

Несколько более общийи более длинное решение

Функция xslt translate(my-xpath-expr,'abcdef','ABCDEF') может использоваться для преобразования шестнадцатеричных чисел в смешанном регистре в шестнадцатеричные в верхнем регистре.Это, вероятно, не обязательно, обычно.

Если вы не знаете длину шестнадцатеричного числа, вы можете добавить «0», как показывает решение Димитра, но вы часто можете уйтис более простым трюком:

<xsl:sort select="string-length(Generation/Sirio/Code)" data-type="number"/>
<xsl:sort select="translate(Generation/Sirio/Code,'abcdef','ABCDEF')"/>

Это работает, если меньшие числа никогда не длиннее больших.Это также работает, если числа могут содержать пробелы или иметь префикс «0x».

Однако, если возможно, лучше всего просто убедиться, что все числа отформатированы одинаково, и сортировать по тексту - ПОЦЕЛУЙТЕ, где это возможно..

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...