将apply-templates的结果与for-each-groups(或问题的替代解决方案)相结合

时间:2011-08-15 15:13:23

标签: xslt xslt-2.0

我收到了根据标题排序的文章列表。除了“主要”标题之外,文章可能有其他标题(甚至多种标题)。当文章确实有替代标题时,文章应该显示为有标题的次数(具有主标题的文章和两个备选标题应该在列表中创建三个条目)。 Simon Christian在这个论坛上发布了一个解决方案来克服这个问题(谢谢),我能够得到理想的清单。

但是,我需要扩展此解决方案。除了列表,我需要一个跳转菜单。所以我必须提取每个标题的第一个字母(包括替代标题),取这些字母并将它们显示在列表的顶部。每个字母都是指向页面上锚点的链接。在列表中,首先可以显示字母“A”,然后是所有以“A”开头的文章,然后是“B”,后面跟所有以“B”开头的文章,依此类推。不应显示那些不是任何标题首字母的字母。

我有一个关于如何获取跳转菜单的旧解决方案,但只有当我必须从源XML中的一个位置提取标题时它才有效。替代标题比主标题更深一些。对于我使用的旧解决方案:

<div class="jumpmenu">
  <xsl:for-each-group group-by="substring(title, 1,1)" select="content">
    <xsl:sort order="ascending" select="substring(title, 1,1)"/>
    <a href="{$url}#{substring(title, 1,1)}"><xsl:value-of select="substring(title, 1,1)"/></a><xsl:text> </xsl:text>
  </xsl:for-each-group>
</div>

但如上所述,它不会考虑替代标题。我可以使用这个来获得所有标题的第一个字母(包括备选方案):

<xsl:apply-templates select="content/title|content/contentdata/alternativetitles/alternativetitle" mode="jumpmenu">
  <xsl:sort select="string(.)" />            
</xsl:apply-templates>

它基本上只获得所有标题的第一个字母并对它们进行排序。我试图找到将这两者结合起来的方法(for-each-group和apply-templates),但没有运气。关于如何做到这一点的任何想法。源XML的示例如下:

<result>
  <element>
    <title>ATitle 1</title>
    <alternative>
      <alternativeTitle>Title 5<alternativeTitle>
    </alternative>
    <data>
      ...
    </data>
  </element>

  <element>
    <title>CTitle 3</title>
    <alternative>
      <alternativeTitle>BTitle 2<alternativeTitle>
      <alternativeTitle>Title 4<alternativeTitle>
    </alternative>
    <data>
      ...
    </data>
  </element>
</result>

我想要的输出类似于:

A  B  C  T          (links to their respective anchors)
A         (anchor)
ATITLE 1 (which is also a link to the full article)
B         (anchor)
BTITLE 2 (which is also a link to the full article)
C         (anchor)
CTITLE 3 (which is also a link to the full article)
T         (anchor)
TITLE 4 (which is also a link to the full article)
TITLE 5 (which is also a link to the full article)

对此的解决方案可能会帮助我解决另一个问题,但如果有人也有这方面的想法,我会介绍它。具有替代标题的文章列在与主标题的第一个字母相同的字母下面。因此,鉴于上述例子,“BTitle 2”列在“C”下。

对于这篇长篇文章感到抱歉,我没有找到任何方法让它缩短并且仍然准确。提前谢谢!

编辑:这是我到目前为止关于问题第二部分的代码:

<xsl:for-each-group group-by="substring(title, 1,1)" select="content">
  <xsl:sort order="ascending" select="substring(title, 1,1)"/>
  <xsl:apply-templates mode="overskrift" select="."/>
  <xsl:apply-templates select="current-group()/title|current-group()/contentdata/alternativetitles/alternativetitle">
    <xsl:sort select="string(.)"/>
  </xsl:apply-templates>
</xsl:for-each-group>

该代码将列出所有标题,但会根据与文章主标题相同的第一个字母列出备选标题。

1 个答案:

答案 0 :(得分:1)

那你为什么不单纯使用

<xsl:for-each-group select="content/title|content/contentdata/alternativetitles/alternativetitle" group-by="substring(., 1, 1)">
   <xsl:sort select="current-grouping-key()"/>
   <a href="{$url}#{current-grouping-key()}"><xsl:value-of select="current-grouping-key()"/></a><xsl:text> </xsl:text>

</xsl:for-each-group>

?您应该将该代码放在与该内容元素的父元素匹配的模板中(我不确定它的路径表达式和发布的XML样本的名称不匹配)。