Если вы хотите отсортировать только смежные element
элементы, то, я думаю, обработка элементов с помощью xsl:for-each-group select="*" group-adjacent="boolean(self::element)
позволяет вам идентифицировать их, а затем внутри for-each-group
вы можете обрабатывать группы element
элементов, отсортированных по атрибут и другие элементы без сортировки:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:math="http://www.w3.org/2005/xpath-functions/math"
xmlns:map="http://www.w3.org/2005/xpath-functions/map"
xmlns:array="http://www.w3.org/2005/xpath-functions/array"
exclude-result-prefixes="xs math map array"
version="3.0">
<xsl:mode on-no-match="shallow-copy"/>
<xsl:output indent="yes"/>
<xsl:template match="measure">
<xsl:copy>
<xsl:for-each-group select="*" group-adjacent="boolean(self::element)">
<xsl:choose>
<xsl:when test="current-grouping-key()">
<xsl:apply-templates select="current-group()">
<xsl:sort select="xs:decimal(@n)"/>
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty -development.net / bFN1y9m /
Если вы хотите отсортировать все дочерние элементы element
и поменять их местами на основе исходной позиции всех дочерних элементов element
, я думаю следующее: сначала вычисляется отсортированная последовательность значений атрибутов, а затем каждый элемент получает сортируется позиция исходного порядка ввода, помогает:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:mode on-no-match="shallow-copy"/>
<xsl:output indent="yes"/>
<xsl:template match="measure">
<xsl:copy>
<xsl:variable name="original-order" as="xs:string*" select="node()!generate-id()"/>
<xsl:variable name="elems" as="element(element)*" select="element"/>
<xsl:variable name="sort-order" as="xs:decimal*" select="sort(element/xs:decimal(@n))"/>
<xsl:apply-templates>
<xsl:sort
select="if (. instance of element(element))
then
let $sort-pos := index-of($sort-order, xs:decimal(@n)),
$orig-el := $elems[$sort-pos]
return
index-of($original-order, $orig-el!generate-id())
else position()"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty -development.net / bFN1y9m / 1
Для процессоров XSLT 3 с функцией высшего порядка sort
поддержка (например, Saxon PE или EE или Altova) Я думаю, что это можно улучшить, если использовать последовательность элементов или идентификаторов элементов для исходного порядка сортировки:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="measure">
<xsl:copy>
<xsl:variable name="original-order" as="xs:string*" select="node()!generate-id()"/>
<xsl:variable name="elems" as="element(element)*" select="element"/>
<xsl:variable name="sort-order" as="xs:decimal*" select="sort(element/xs:decimal(@n))"/>
<xsl:apply-templates>
<xsl:sort
select="if (. instance of element(element))
then
let $sort-pos := index-of($sort-order, xs:decimal(@n)),
$orig-el := $elems[$sort-pos]
return
index-of($original-order, $orig-el!generate-id())
else position()"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Таким образом, я думаю, что подход должен работать, даже если существуют различные элементы с одинаковым значением ключа сортировки (например, @n
значение).