我正在尝试找出一种(相对)有效的方法来排序XSLT中的元素,这样我就不必回到我的Java代码中并弄乱DOM了。
如果我有这样的文件:
<?xml-stylesheet type="text/xsl" href="test.xsl"?>
<Root>
<Player name="Jane Doe">
<Location distance="90"/>
<Location distance="45"/>
</Player>
<Player name="John Doe">
<Location distance="50"/>
<Location distance="20"/>
</Player>
</Root>
我的目标是按最近位置的距离对球员进行排序。换句话说,由于John Doe的位置在20英里范围内,他距离更近,他的节点需要在最近位置为45英里的Jane Doe之上进行分类。
这样的事情是否可能?如果没有,没有大事。在开始操作DOM之前,我只是想把它扔出去。
答案 0 :(得分:2)
这是一个简短的XSLT 1.0转换:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*">
<xsl:copy>
<xsl:apply-templates>
<xsl:sort select="*/@distance[not(. > ../../*/@distance)]" data-type="number"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
在提供的XML文档上应用此转换时:
<Root>
<Player name="Jane Doe">
<Location distance="90"/>
<Location distance="45"/>
</Player>
<Player name="John Doe">
<Location distance="50"/>
<Location distance="20"/>
</Player>
</Root>
生成了正确排序的结果:
<Root>
<Player name="John Doe">
<Location distance="50"/>
<Location distance="20"/>
</Player>
<Player name="Jane Doe">
<Location distance="90"/>
<Location distance="45"/>
</Player>
</Root>
答案 1 :(得分:0)
使用XSLT 2.0(和Saxon 9之类的XSLT 2.0处理器)可以使用
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:output indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* , node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Root">
<xsl:copy>
<xsl:apply-templates select="Player">
<xsl:sort select="min(Location/@distance)"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
这是一个XSLT 1.0解决方案,使用exsl:node-set
处理在变量中创建的结果树片段,其中使用通常的XSLT 1.0排序方法识别最小距离并按排序顺序获取第一个项目: / p>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:exsl="http://exslt.org/common"
exclude-result-prefixes="exsl">
<xsl:output indent="yes"/>
<xsl:variable name="players-rtf">
<xsl:for-each select="Root/Player">
<xsl:copy>
<xsl:attribute name="min-dist">
<xsl:for-each select="Location/@distance">
<xsl:sort select="." data-type="number"/>
<xsl:if test="position() = 1">
<xsl:value-of select="."/>
</xsl:if>
</xsl:for-each>
</xsl:attribute>
<xsl:copy-of select="@* | *"/>
</xsl:copy>
</xsl:for-each>
</xsl:variable>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Root">
<xsl:copy>
<xsl:apply-templates select="exsl:node-set($players-rtf)/Player">
<xsl:sort select="@min-dist" data-type="number"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="Player/@min-dist"/>
</xsl:stylesheet>