XSLT按字母顺序排序&数字问题

时间:2010-04-19 19:31:51

标签: xslt sorting alphanumeric

我有一组字符串,即g:lines ='9,1,306,LUCY,G,38,12'

我需要输出在XSLT 1.0中:

1,9,12,38,306,G,LUCY

这是我目前的代码:

<xsl:for-each select="$all_alerts[g:problem!='normal_service'][g:service='bus']">
  <xsl:sort select="g:line"/>
  <xsl:sort select="number(g:line)" data-type="number"/>
  <xsl:value-of select="normalize-space(g:line)" /><xsl:text/>
  <xsl:if test="position()!=last()"><xsl:text>,&#160;</xsl:text></xsl:if>
</xsl:for-each>

我可以让它只显示'1,12,306,38,9,G,LUCY',因为没有拾取第2种。

任何人都可以帮助我吗?

4 个答案:

答案 0 :(得分:11)

要使用一个xsl:foreach语句实现此目的,请尝试以下操作:

<xsl:for-each select="$all_alerts[g:problem!='normal_service'][g:service='bus']"> 
  <xsl:sort select="not(number(g:line))"/> 
  <xsl:sort select="number(g:line)" data-type="number"/> 
  <xsl:sort select="g:line"/> 
  <xsl:value-of select="normalize-space(g:line)" /><xsl:text/> 
  <xsl:if test="position()!=last()"><xsl:text>,&#160;</xsl:text></xsl:if> 
</xsl:for-each> 

第一个 xsl:sort 对该行是否为数字进行排序。如果该行是数字, not()将返回false,如果不是,则返回true。 false在true之前排序,因此数字首先出现。如果省略此类,则首先显示字母。

下一个 xsl:sort 按数字排序,因此会正确排序数字,但不会影响字母(当应用数字()时都会返回NaN。)

最终的 xsl:sort 会按字母顺序对字母进行排序。

答案 1 :(得分:0)

<xsl:template match="/">
  <xsl:for-each select="(9,1,306,'LUCY','G',89)" >
    <xsl:sort select="if (number()) then () else ."/>
    <xsl:sort select="number(.)" data-type="number" />
    <xsl:value-of select="."/>
    <xsl:value-of select="', '" />
  </xsl:for-each>
</xsl:template>

给了我

1,9,89,306,G,LUCY,

我想这就是你需要的,对吗?

答案 2 :(得分:0)

在XSLT 1.0中,我认为你需要这样的东西:

<xsl:for-each select="$all_alerts[g:problem!='normal_service'][g:service='bus']">  
    <xsl:sort select="g:line[number(g:line) != number(g:line)]"/>  
    <xsl:sort select="g:line[number(g:line) = number(g:line)]" data-type="number"/>
    <xsl:value-of select="normalize-space(g:line)" /><xsl:text/>  
    <xsl:if test="position()!=last()"><xsl:text>,&#160;</xsl:text></xsl:if>  
</xsl:for-each>

number($ foo)!= number($ foo)是XSLT 1.0习语,用于测试值是否为数字。

另一个(我猜的更干净)解决方案是选择/排序第一个数字,然后是其他数字。

答案 3 :(得分:0)

我相信这可以实现你想要的。

我首先拆分评估/排序数字,然后拆分文本节点值。

    <xsl:for-each select="$all_alerts[g:problem!='normal_service'][g:service='bus'][number(g:line)=number(g:line)]">
        <xsl:sort select="g:line" data-type="number" order="ascending"/>
        <xsl:value-of select="normalize-space(g:line)" />
        <xsl:text/>
        <xsl:if test="position()!=last() or $all_alerts[g:problem!='normal_service'][g:service='bus'][number(g:line)!=number(g:line)]">
            <xsl:text>,&#160;</xsl:text>
        </xsl:if>
    </xsl:for-each>

    <xsl:for-each select="$all_alerts[g:problem!='normal_service'][g:service='bus'][number(g:line)!=number(g:line)]">
        <xsl:sort select="g:line[number(g:line) != number(g:line)]"/>
        <xsl:value-of select="normalize-space(g:line)" />
        <xsl:text/>
        <xsl:if test="position()!=last()">
            <xsl:text>,&#160;</xsl:text>
        </xsl:if>
    </xsl:for-each>