Я пытаюсь отсортировать свой преобразованный вывод по элементу, который содержит шестнадцатеричное значение.
<xsl:sort select="Generation/Sirio/Code" data-type="number"/>
Значения являются простым Шестнадцатеричным числом: 00 01 02 ... 0A ... FF
но они становятся отсортированными как этот: 0A FF 00 01 02
, который указывает, что метод сортировки перестал работать, как только существует включенный символ.
Как я могу работать вокруг этого?
Большое спасибо!
Это преобразование :
<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
содержит эту строку нулей и используется для заполнения нулями слева каждого ключа сортировки, чтобы все ключи сортировки имели одинаковую длину.
Просто удалите 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, где это возможно.