XSLT排序问题

时间:2015-12-15 13:23:51

标签: xml sorting xslt

我有一个xml,如:

<PersonList>            
<Person>
    <Name>Smith</Name>
    <Role>5</Role>
</Person>
 <Person>
    <Name>Star</Name>
    <Role>3</Role>
</Person>
<Person>
    <Name>Wars</Name>
    <Role>1</Role>
</Person>    
</PersonList> 

在xslt中我想以这样的方式排序:如果有一个角色1,这应该是列表中的第一个Person。 其余人员应按名称按字母顺序排序。

提前致谢。

2 个答案:

答案 0 :(得分:3)

以这种方式尝试:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<!-- identity transform -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="/PersonList">
    <xsl:copy>
        <xsl:apply-templates select="Person">
            <xsl:sort select="number(Role=1)" data-type="number" order="descending"/>
            <xsl:sort select="Name" data-type="text" order="ascending"/>
        </xsl:apply-templates>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

或者,如果您愿意:

...
<xsl:template match="/PersonList">
    <xsl:copy>
        <xsl:apply-templates select="Person[Role=1]"/>
        <xsl:apply-templates select="Person[not(Role=1)]">
            <xsl:sort select="Name" data-type="text" order="ascending"/>
        </xsl:apply-templates>
    </xsl:copy>
</xsl:template>
...

附加说明:

表达式Role=1返回布尔结果。但是,XSLT 1.0的xsl:sort指令只能按文本或数字排序。因此,结果必须先转换为字符串或数字,然后才能用于排序。

我更喜欢将布尔值转换为数字,因为在阅读代码时,预期的顺序更容易理解。

出于同样的原因,我更愿意明确说明data-typeorder,即使它们分别是“text”和“ascending”的默认值。

在任何情况下,如果一个人更喜欢按文本排序,那么所需的过程在复杂性方面相同 1

<xsl:sort select="not(Role=1)"/>

只是简称:

<xsl:sort select="string(not(Role=1))" data-type="text" order="ascending"/>

与以下内容相同:

<xsl:sort select="string(Role=1)" data-type="text" order="descending"/>

这三者之间的唯一区别在于代码可读性。

(1)有人可能会争辩说,数字排序比按字母顺序排序更有效,但我不知道这是事实,所以我不会。

注意:
这些差异很小,很大程度上取决于个人偏好。

答案 1 :(得分:2)

更简单,更简短的解决方案 - 无需数字排序

<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 select="*">
        <xsl:sort select="not(Role=1)"/>
        <xsl:sort select="Name"/>
      </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

<强>解释

  1. 对布尔值进行排序时,false() true()之前会出现

  2. 多键排序