XSLT自定义排序

Xet*_*ius 3 sorting xslt

是否可以在XSLT中按字母顺序排序,将5个项目作为"首选".

即给定

<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>
Run Code Online (Sandbox Code Playgroud)

我要求国家队按照特定顺序排序,其余按字母顺序排列:

<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>
Run Code Online (Sandbox Code Playgroud)

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

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

Dir*_*mar 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>
Run Code Online (Sandbox Code Playgroud)

请注意,您必须使用反转第一个条件not().原因是表达式的布尔结果被转换为数字(0表示false,1表示为true),因此将首先列出评估为"false"的项目.


Tom*_*lak 6

你可以这样做:

<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>
Run Code Online (Sandbox Code Playgroud)

整个<my:data>可以移动到辅助XML /配置文件,您也可以在其中省略"我的"命名空间.

在那之后,一行需要一个小的改变:

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

上面的输出有点不足为奇:-)

<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>
Run Code Online (Sandbox Code Playgroud)