2009-08-17 94 views
3

XSLT是否可以按字母顺序进行排序,其中5项为“首选”。XSLT自定义排序

即给予

<teams> 
<team id="142" name="Scotland" /> 
<team id="110" name="Liverpool" /> 
<team id="13" name="Manchester United" /> 
<team id="123" name="England" /> 
<team id="84" name="Chelsea" /> 
<team id="295" name="Wales" /> 
<team id="49" name="Arsenal" /> 
<team id="126" name="Northern Ireland" /> 
<team id="121" name="Republic of Ireland" /> 
<team id="42" name="Manchester City" /> 
<team id="298" name="Tottenham Hotspur" /> 
<team id="299" name="Bolton" /> 
</teams> 

我要求国家队在一定的顺序先进行排序,然后按字母顺序休息:

<teams> 
<team id="123" name="England" /> 
<team id="126" name="Northern Ireland" /> 
<team id="121" name="Republic of Ireland" /> 
<team id="142" name="Scotland" /> 
<team id="295" name="Wales" /> 
<team id="49" name="Arsenal" /> 
<team id="299" name="Bolton" /> 
<team id="84" name="Chelsea" /> 
<team id="110" name="Liverpool" /> 
<team id="42" name="Manchester City" /> 
<team id="13" name="Manchester United" /> 
<team id="298" name="Tottenham Hotspur" /> 
</teams> 

我一直在努力,但失败了。

有没有一个简单的方法来做到这一点,或者你必须单独对国家队进行排序,然后排除所有国家队?

回答

5

你可以这样做:

<xsl:stylesheet 
    version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:my="http://tempuri.org" 
    exclude-result-prefixes="my" 
> 

    <xsl:output method="xml" indent="yes" /> 

    <my:data> 
    <my:nationalteams> 
     <my:team id="121" /><!-- Republic of Ireland --> 
     <my:team id="123" /><!-- England --> 
     <my:team id="126" /><!-- Northern Ireland --> 
     <my:team id="142" /><!-- Scotland --> 
     <my:team id="295" /><!-- Wales --> 
    </my:nationalteams> 
    </my:data> 

    <xsl:template match="teams"> 
    <xsl:copy> 
     <xsl:variable name="national" select=" 
     document('')/*/my:data/my:nationalteams/my:team 
     " /> 
     <!-- national teams preferred --> 
     <xsl:apply-templates select="team[@id = $national/@id]"> 
     <xsl:sort select="@name" /> 
     </xsl:apply-templates> 
     <!-- other teams after them --> 
     <xsl:apply-templates select="team[not(@id = $national/@id)]"> 
     <xsl:sort select="@name" /> 
     </xsl:apply-templates> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="team"> 
    <xsl:copy-of select="." /> 
    </xsl:template> 

</xsl:stylesheet> 

整个<my:data>可以移动到二级XML/config文件,在这里你也可以离开过“我的”命名空间。

之后,一条线就需要一个小的变化:

<xsl:variable name="national" select=" 
    document('config.xml')/data/nationalteams/team 
" /> 

的上面的输出是有点令人吃惊:-)

<teams> 
    <team id="123" name="England" /> 
    <team id="126" name="Northern Ireland" /> 
    <team id="121" name="Republic of Ireland" /> 
    <team id="142" name="Scotland" /> 
    <team id="295" name="Wales" /> 
    <team id="49" name="Arsenal" /> 
    <team id="299" name="Bolton" /> 
    <team id="84" name="Chelsea" /> 
    <team id="110" name="Liverpool" /> 
    <team id="42" name="Manchester City" /> 
    <team id="13" name="Manchester United" /> 
    <team id="298" name="Tottenham Hotspur" /> 
</teams> 
1

你见过的xsl:sort元素,你可以通过组合XSL创建两个或多个分类准则:应用模板和xsl:排序

Indeeed,这里是一些国家至上的样本,在预定订单, 然后所有其他。 请注意,这些是元素,而不是上面的属性。

<xsl:sort select="not(CountryValue = 'Scotland')"/> 
<xsl:sort select="not(CountryValue = 'India')"/> 
<xsl:sort select="CountryValue"/> 

样品结果:

国家

Scotland 
Scotland 
Scotland 
India 
Afghanistan 
Afghanistan 
Afghanistan 
Afghanistan 
Afghanistan 
Afghanistan 
Albania 
Albania 
Albania 
Algeria 
1

在你的XSLT,你可以使用扩展函数?

如果是这样,一种方法是在线修改现有节点列表,以创建新节点集,但在每个节点上具有额外的“sortname”属性。然后,您可以通过这个新的节点集合迭代,使用新的“sortname”属性排序:以上

<?xml version="1.0"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="urn:schemas-microsoft-com:xslt"> 
    <xsl:output method="xml" /> 
    <xsl:template match="/teams"> 
     <xsl:variable name="extendedteams"> 
     <xsl:for-each select="team"> 
      <xsl:copy> 
       <xsl:copy-of select="@*" /> 
       <xsl:attribute name="sortname"> 
        <xsl:choose> 
         <xsl:when test="@name='England' or @name='Northern Ireland' or @name='Republic of Ireland' or @name='Scotland' or @name='Wales'">1</xsl:when> 
         <xsl:otherwise>2</xsl:otherwise> 
        </xsl:choose> 
        <xsl:value-of select="@name" /> 
       </xsl:attribute> 
      </xsl:copy> 
     </xsl:for-each> 
     </xsl:variable> 
     <xsl:copy> 
     <xsl:for-each select="exsl:node-set($extendedteams)/team"> 
      <xsl:sort select="@sortname" /> 

      <xsl:copy> 
       <xsl:copy-of select="@*[name() != 'sortname']" /> 
      </xsl:copy> 
     </xsl:for-each> 
     </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

在这个例子中,我在它前面加上“1”到任何国家队和“2”的任何国内团队,然后排序这个新属性。

查看有关Node Sets的信息,了解XSLT处理器支持哪些扩展。

11

添C已已经给一个很好的答案,但也许更简单的方法就足够你的情况。按字母顺序第一个将排序首选/非首选项目,第二个名字:您可以简单地指定两个xsl:sort条件

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="/teams"> 
    <teams> 
     <xsl:for-each select="team"> 
     <xsl:sort select="not(@name = 'England' or @name='Northern Ireland' 
          or @name='Republic of Ireland' 
          or @name='Scotland' or @name='Wales')" 
        data-type="number"/> 
     <xsl:sort select="@name"/> 
     <team> 
      <xsl:value-of select="@name"/> 
     </team> 
     </xsl:for-each> 
    </teams> 
    </xsl:template> 
</xsl:stylesheet> 

请注意,您必须使用反转的not()首要条件。其原因是,表达式的布尔值结果被转换成一个数字(0是假的,1为真),因此评价为“假”的项目将被首先列出。

+0

你的答案是比我好得多。你的无需扩展功能! – 2009-08-17 13:40:31

+0

然而,扩展功能为您提供了更大的灵活性,恕我直言。 – 2009-08-17 14:00:53