如何通过数值对节点进行排序,而不是所有节点都具有该值?

时间:2015-12-29 22:01:21

标签: xslt

我有一个这样的XML文档:

<?xml version="1.0" ?>
<root>
  <element id="1"><name>Red</name><rank value="1" /></element>
  <element id="2"><name>Orange</name><rank value="4" /></element>
  <element id="3"><name>Yellow</name><rank value="3" /></element>
  <element id="4"><name>Green</name><rank value="2" /></element>
  <element id="5"><name>Blue</name><rank value="5" /></element>
  <element id="6"><name>Indigo</name></element>
  <element id="6"><name>Violet</name></element>
</root>

我希望按数字排序排序,并将未排名的元素浮动到底部,如下所示:

  • 红色
  • 绿色
  • 黄色
  • 靛蓝

Indigo / Violet的顺序与我无关。

我试过了:

<?xml version="1.0" ?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/root">
    <xsl:apply-templates select="element">
      <xsl:sort select="rank/@value" data-type="number" order="ascending" />
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="element">
    <xsl:text>* </xsl:text><xsl:apply-templates select="name" /><xsl:text>
</xsl:text>
  </xsl:template>
</xsl:stylesheet>

但我的输出看起来像这样:

  • 靛蓝
  • 红色
  • 绿色
  • 黄色

所有排名的项目实际上都是有序的,但它们位于列表的底部。

3 个答案:

答案 0 :(得分:1)

经过一些修补后回答我自己的问题。

由于我使用的是数字排序条件,因此我可以对descending进行排序,而不是ascending,然后翻转要排序的数字参数的符号:

<xsl:apply-templates select="element">
  <xsl:sort select="-(rank/@value)" data-type="number" order="descending" />
</xsl:apply-templates>

这给出了所需的顺序:

  • 红色
  • 绿色
  • 黄色
  • 靛蓝

答案 1 :(得分:1)

我建议采用更通用的方法:

<xsl:template match="/root">
    <xsl:apply-templates select="element">
        <xsl:sort select="number(boolean(rank/@value))" data-type="number" order="descending" />
        <xsl:sort select="rank/@value" data-type="number" order="ascending" />
    </xsl:apply-templates>
</xsl:template>

参见说明:https://stackoverflow.com/a/34290573/3016153

答案 2 :(得分:0)

  <xsl:template match="/*">
    <xsl:apply-templates select="element">
      <xsl:sort select="not(rank/@value)"/>
      <xsl:sort select="rank/@value" data-type="number"/>
    </xsl:apply-templates>
  </xsl:template>