【问题标题】:Ignoring 'A' and 'The' when sorting with XSLT使用 XSLT 排序时忽略“A”和“The”
【发布时间】:2010-05-17 11:35:38
【问题描述】:

我想要一个列表排序,忽略任何初始定冠词“the”和“a”。例如:

  • 错误喜剧
  • 哈姆雷特
  • 仲夏夜之梦
  • 第十二夜
  • 冬天的故事

我认为也许在 XSLT 2.0 中这可以通过以下方式实现:

<xsl:template match="/">
  <xsl:for-each select="play"/>
    <xsl:sort select="if (starts-with(title, 'A ')) then substring(title, 2) else
                      if (starts-with(title, 'The ')) then substring(title, 4) else title"/>
    <p><xsl:value-of select="title"/></p>
  </xsl:for-each>
</xsl:template>

但是,我想使用浏览器内处理,所以必须使用 XSLT 1.0。有没有办法在 XLST 1.0 中实现这一点?

【问题讨论】:

  • 通常正确的方法是为每个元素存储一个“排序标题”,因为规则可能变得非常复杂,甚至扩展到其他语言(例如“Die”是一篇文章,应该在德语中被忽略,但“Die Hard”不应该在“H”下排序,即使在德语索引中找到)。 “仲夏夜之梦”的排序标题将是“仲夏夜之梦,A”。
  • 我应该提到,starts-with() 在 XLST 1.0 中可用,但 if-then-else 不是...
  • @Joachim - 你说得对,但我需要处理现有数据,没有资源来维护并行排序字段; Gart 的 quick-n-dirty 解决方案正是我所需要的——不过评论很好
  • 好问题! (+1)。请参阅我的答案以获得完整的解决方案。

标签: sorting xslt xslt-1.0


【解决方案1】:

这种转变

<xsl:template match="plays">
 <p>Plays sorted by title: </p>
    <xsl:for-each select="play">
      <xsl:sort select=
      "concat(@title
               [not(starts-with(.,'A ') 
                  or 
                   starts-with(.,'The '))],
              substring-after(@title[starts-with(., 'The ')], 'The '),
              substring-after(@title[starts-with(., 'A ')], 'A ')
              )
     "/>
      <p>
        <xsl:value-of select="@title"/>
      </p>
    </xsl:for-each>
</xsl:template>

应用于此 XML 文档时

产生想要的正确结果

<p>Plays sorted by title: </p>
<p>Barber</p>
<p>The Comedy of Errors</p>
<p>CTA &amp; Fred</p>
<p>Hamlet</p>
<p>A Midsummer Night's Dream</p>
<p>Twelfth Night</p>
<p>The Winter's Tale</p>

【讨论】:

  • 第二个优秀的解决方案,Dimitre,它避免了 Gart 解决方案的数学 - 也谢谢!由于我不得不稍微考虑一下,所以我会为其他人添加一些好处:例如,对于“The Winter's Tale”,它将排序的值将是“Winter's TaleThe Winter's Tale”。
  • @ChrisV:是的,这个解决方案的优点是它更简单,并且在做算术时犯错的机会更少。尽管排序键看起来很奇怪,但这不会影响最终输出的值。
  • 如果“The”是文本的中间,可能会出现问题,更像是“...Something The Something..”(抱歉,想不出任何真实的例子)。此外,一般情况下,冠词“An”也应相应处理。
  • @Gart:当然可以。但是这个问题严格地说文章是在戏剧的开始——为了排序而消除任何中间词是没有意义的。
  • 我发现的一个极端情况是,当项目以“CTA & Fred”的形式排序时,条目将根据&amp;amp; 进行排序。这不是“The”的问题,而是更容易匹配“A”的问题。
【解决方案2】:

我会这样做:

<xsl:template match="plays">
    <xsl:for-each select="play">
      <xsl:sort select="substring(title, 1 + 2*starts-with(title, 'A ') + 4*starts-with(title, 'The '))"/>
      <p>
        <xsl:value-of select="title"/>
      </p>
    </xsl:for-each>
</xsl:template>

更新我忘了给表达式加 1(经典的非一错误)

嗯,starts-with 来自 XSLT 1.0。证明链接:Google 中的第一个搜索结果产生XSLT 1.0: function starts-with

【讨论】:

  • 问题在于 starts-with 是 XSLT 2.0,我认为 - 编辑我已更正!
  • 我在23分钟前一发帖子就纠正了自己,我只是不想删除原来的评论,因为删除自己的错误似乎很可疑。干杯。
  • 出色的简单创意解决方案 Gart - 谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-03-16
  • 2010-09-09
  • 2011-08-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多