Xml 按子元素的属性值排序父元素
我正试图找出一种(相对)有效的方法来对XSLT中的元素进行排序,这样我就不必回到Java代码中去处理DOM了 如果我有这样一个文件:Xml 按子元素的属性值排序父元素,xml,xslt,Xml,Xslt,我正试图找出一种(相对)有效的方法来对XSLT中的元素进行排序,这样我就不必回到Java代码中去处理DOM了 如果我有这样一个文件: <?xml-stylesheet type="text/xsl" href="test.xsl"?> <Root> <Player name="Jane Doe"> <Location distance="90"/> <Location distance="45"/> </P
<?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英里以内,所以他离得更近,他的节点需要排序在Jane Doe的上方,Jane Doe最近的位置是45英里
这样的事情可能吗?如果没有,没什么大不了的。在开始DOM操作之前,我只想把这个问题抛到一边。使用XSLT2.0(以及类似Saxon 9的XSLT2.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转换:
<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>
<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>
当此转换应用于提供的XML文档时:
<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>
<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>
生成所需的正确排序结果:
<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>
<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>
我对尝试摸索有点恼火,为什么每个玩家元素中都有两个距离元素,如果这很重要,并且像排序顺序一样恒定,如果一个解决方案应该/能够考虑到这一点?在XSLT2.0中,这很容易,例如,
,因此假设您的DOM代码是Java DOM代码,您可以使用XSLT2.0和Saxon 9而不是DOM。XSLT 1.0当然也可以,但可能需要两个步骤,首先确定每个播放器的最小距离,然后根据第一步的结果对它们进行排序。这是因为您查看的数据只是我在企业世界中使用的数据的演示。请放心,我使用的真实数据有多个“位置”(没有,不是节点)的原因。Martin Honnen-不幸的是,我们使用XSLT 1.0,因为我们正在处理一个旧的工作环境。我相信我们运行的是Java 6…即使Java 8也没有Oracle的XSLT 2.0,但只使用Saxonica的Saxon,我认为Saxon应该使用Java 6。Dimitre,非常感谢!在Kay之外,在阅读XSL文章时,您是我唯一信任的“权威”。你似乎对每个问题都有答案。