XSLT 中的某种冒泡排序
Some kind of bubble sort in XSLT
我想按属性 top
的值对所有 <text>
元素进行排序。
但是,只有当元素的前一个兄弟元素的值 top
超过其本身的 2 个或更多单位时,才应对其进行排序。
例如下面的元素
<text top="100">text 1</text>
<text top="99">text 2</text>
<text top="100">text 3</text>
<text top="99">text 4</text>
<text top="35">text 5</text>
<text top="40">text 6</text>
应转换为:
<text top="35">text 5</text>
<text top="40">text 6</text>
<text top="100">text 1</text>
<text top="99">text 2</text>
<text top="100">text 3</text>
<text top="99">text 4</text>
这样的群:
<text top="100">text 1</text>
<text top="99">text 2</text>
<text top="100">text 3</text>
<text top="99">text 4</text>
排序后保持原样。
我只是偶尔用XSLT,只知道常用的排序方式:
<xsl:for-each select="text">
<xsl:sort select="@top" />
<xsl:copy>
<xsl:copy-of select="./node()|./@*" />
</xsl:copy>
</xsl:for-each>
但我想要达到的结果需要某种冒泡排序。
不确定它是否适用于纯 XSLT。
我有一个 XSLT 2.0 处理器。
据我了解,要求是先分组再排序。请注意,假设其元素的增量小于 2 个单位的组在其他组中排序,只考虑最小值(意味着组不重叠)。
此样式表:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:template match="*[text]">
<xsl:for-each-group
select="text"
group-adjacent="boolean(
(preceding-sibling::text[1]
|following-sibling::text[1])
[abs(@top - current()/@top) < 2])">
<xsl:sort select="min(@top)"/>
<xsl:choose>
<xsl:when test="current-grouping-key()">
<xsl:copy-of select="current-group()"/>
</xsl:when>
<xsl:otherwise>
<xsl:perform-sort select="current-group()">
<xsl:sort select="@top" data-type="number"/>
</xsl:perform-sort>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
输出:
<text top="35">text 5</text>
<text top="40">text 6</text>
<text top="100">text 1</text>
<text top="99">text 2</text>
<text top="100">text 3</text>
<text top="99">text 4</text>
在here
中测试
编辑:不假设仅使用 abs()
函数增加序列。
我想知道在 XSLT 2/3 中是否可以使用适当的 group-ending-with
模式来完成:
<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:param name="limit" as="xs:integer" select="1"/>
<xsl:output indent="yes"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="root">
<xsl:for-each-group select="text" group-ending-with="text[abs(xs:decimal(following-sibling::text[1]/@top) - xs:decimal(@top)) > $limit]">
<xsl:sort select="min(current-group()/@top/xs:decimal(.))"/>
<xsl:sequence select="current-group()"/>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
基于大大简化的 XQuery 代码
for tumbling window $group in root/text
start when true()
end $e next $ne when abs(xs:decimal($ne/@top) - xs:decimal($e/@top)) > 1
order by min($group/@top/xs:decimal(.))
return
$group
我想按属性 top
的值对所有 <text>
元素进行排序。
但是,只有当元素的前一个兄弟元素的值 top
超过其本身的 2 个或更多单位时,才应对其进行排序。
例如下面的元素
<text top="100">text 1</text>
<text top="99">text 2</text>
<text top="100">text 3</text>
<text top="99">text 4</text>
<text top="35">text 5</text>
<text top="40">text 6</text>
应转换为:
<text top="35">text 5</text>
<text top="40">text 6</text>
<text top="100">text 1</text>
<text top="99">text 2</text>
<text top="100">text 3</text>
<text top="99">text 4</text>
这样的群:
<text top="100">text 1</text>
<text top="99">text 2</text>
<text top="100">text 3</text>
<text top="99">text 4</text>
排序后保持原样。
我只是偶尔用XSLT,只知道常用的排序方式:
<xsl:for-each select="text">
<xsl:sort select="@top" />
<xsl:copy>
<xsl:copy-of select="./node()|./@*" />
</xsl:copy>
</xsl:for-each>
但我想要达到的结果需要某种冒泡排序。
不确定它是否适用于纯 XSLT。 我有一个 XSLT 2.0 处理器。
据我了解,要求是先分组再排序。请注意,假设其元素的增量小于 2 个单位的组在其他组中排序,只考虑最小值(意味着组不重叠)。
此样式表:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:template match="*[text]">
<xsl:for-each-group
select="text"
group-adjacent="boolean(
(preceding-sibling::text[1]
|following-sibling::text[1])
[abs(@top - current()/@top) < 2])">
<xsl:sort select="min(@top)"/>
<xsl:choose>
<xsl:when test="current-grouping-key()">
<xsl:copy-of select="current-group()"/>
</xsl:when>
<xsl:otherwise>
<xsl:perform-sort select="current-group()">
<xsl:sort select="@top" data-type="number"/>
</xsl:perform-sort>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
输出:
<text top="35">text 5</text>
<text top="40">text 6</text>
<text top="100">text 1</text>
<text top="99">text 2</text>
<text top="100">text 3</text>
<text top="99">text 4</text>
在here
中测试编辑:不假设仅使用 abs()
函数增加序列。
我想知道在 XSLT 2/3 中是否可以使用适当的 group-ending-with
模式来完成:
<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:param name="limit" as="xs:integer" select="1"/>
<xsl:output indent="yes"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="root">
<xsl:for-each-group select="text" group-ending-with="text[abs(xs:decimal(following-sibling::text[1]/@top) - xs:decimal(@top)) > $limit]">
<xsl:sort select="min(current-group()/@top/xs:decimal(.))"/>
<xsl:sequence select="current-group()"/>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
基于大大简化的 XQuery 代码
for tumbling window $group in root/text
start when true()
end $e next $ne when abs(xs:decimal($ne/@top) - xs:decimal($e/@top)) > 1
order by min($group/@top/xs:decimal(.))
return
$group