Как отсортировать по hexadecimals в xslt?

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

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

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

Как я могу работать вокруг этого?

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

6
задан atamanroman 14 June 2010 в 13:36
поделиться

2 ответа

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

<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 содержит эту строку нулей и используется для заполнения нулями слева каждого ключа сортировки, чтобы все ключи сортировки имели одинаковую длину.

2
ответ дан 17 December 2019 в 18:10
поделиться

Простейшее решение

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

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

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

Немного более общее и длинное решение

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

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

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

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

Однако, если возможно, вам лучше просто убедиться, что все числа отформатированы одинаково и отсортированы по тексту - KISS, где это возможно.

1
ответ дан 17 December 2019 в 18:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: