草庐IT

xml - XSLT 按子元素排序和分组

coder 2024-06-30 原文

`我有一个 XML 文件,其中包含很多“入口”节点。在每个“条目”节点中,通常有一个“年份”和“标题”子节点。

我正在尝试生成如下所示的 HTML 输出:

2012
    Title
    Title

2011
    Title

2010
    Title
    Title

只要具有唯一年份的条目存在,这种模式就应该继续。我无法让它只打印一次年份。我可以让它每年打印一次,但它只会打印一个(假设是第一个)条目的标题。我可以让它打印每个条目的年份,但它会显示每个条目的年份。我使用了变量、生成 ID 和 key 的组合,但遇到了描述的问题(我可能做错了每一个)。

  • 对年数、参赛作品数量或每年/组的参赛作品数量没有限制。
  • 每年只应显示一次。

就 HTML 而言,我希望每个子组(共享一年)都在其自己的有序列表中,但如果这不可能,我也不会感到惊讶!

.

我正在使用的 XML 文件的一般模式是这样的:

root
    Entry
        Title
        Year

<root>
    <Entry>
        <Title>Num 1</Title>
        <Year>1991</Year>
    </Entry>
    <Entry>
        <Title>Num 2</Title>
        <Year>2011</Year>
    </Entry>
    <Entry>
        <Title>Num 3</Title>
        <Year>2012</Year>
    </Entry>
    <Entry>
        <Title>Num 4</Title>
        <Year>2012</Year>
    </Entry>
</root>

XSL 版本 1.0 或 2.0 都可以。

这是 Entry 的模板匹配(它只获取元素并将所有内容放在单行列表项中)。

  •     <xsl:if test="Download">
      <xsl:text disable-output-escaping="yes">&lt;a href="http://thisisnot.real/publications/</xsl:text>
      <xsl:value-of select="Download"/>
      <xsl:text disable-output-escaping="yes">"&gt;</xsl:text>
        </xsl:if>
        <xsl:value-of select="Title"/>
        <xsl:if test="Download">
      <xsl:text disable-output-escaping="yes">&lt;/a&gt;</xsl:text>
        </xsl:if>
        <xsl:text>, </xsl:text>
    
     <!-- Add the handling for (possibly multiple) Authors -->
     <xsl:for-each select="Author">
         <xsl:value-of select="."/>,
     </xsl:for-each>
    
    
    
    
        <xsl:text>In </xsl:text>
        <EM>
          <xsl:value-of select="Booktitle"/>
        </EM>
        <xsl:text>, </xsl:text>
    
     <!-- Add the handling for Page -->
     <xsl:if test="Page">
          page <xsl:value-of select="Page"/>,
     </xsl:if>
    
     <!-- Add the handling for Address -->
     <xsl:if test="Address">
        <xsl:value-of select="Address"/>,
     </xsl:if>
    
     <!-- Add the handling for Year-Convert numeric Month to letters: eg, from 1 to January -->
     <xsl:for-each select="Month">
        <xsl:choose>
           <xsl:when test=".=1">January <xsl:value-of select="../Year"/></xsl:when>
           <xsl:when test=".=2">February <xsl:value-of select="../Year"/></xsl:when>
           <xsl:when test=".=3">March <xsl:value-of select="../Year"/></xsl:when>
           <xsl:when test=".=4">April <xsl:value-of select="../Year"/></xsl:when>
           <xsl:when test=".=5">&gt;May <xsl:value-of select="../Year"/></xsl:when>
           <xsl:when test=".=6">June <xsl:value-of select="../Year"/></xsl:when>
           <xsl:when test=".=7">July <xsl:value-of select="../Year"/></xsl:when>
           <xsl:when test=".=8">August <xsl:value-of select="../Year"/></xsl:when>
           <xsl:when test=".=9">September <xsl:value-of select="../Year"/></xsl:when>
           <xsl:when test=".=10">October <xsl:value-of select="../Year"/></xsl:when>
           <xsl:when test=".=11">November <xsl:value-of select="../Year"/></xsl:when>
           <xsl:when test=".=12">December <xsl:value-of select="../Year"/></xsl:when>
        </xsl:choose>
     </xsl:for-each>
    
     <!-- Add the handling for Note -->
     <xsl:if test="Note">
             <em>(<xsl:value-of select="Note"/>)</em>
     </xsl:if>
    
     <!-- Add the handling for AcceptRate in the grey color: #333333 -->
     <xsl:if test="AcceptRate">
         <font color="#333333"><small>  Acceptance Rate: <xsl:value-of select="AcceptRate"/></small></font>
     </xsl:if>
    
     <!-- Add the handling for Award in the red color: #ff0000 -->
     <xsl:if test="Award">
         <font color="#ff0000"><strong> (<xsl:value-of select="Award"/>)</strong></font>
     </xsl:if>
    

      </LI>
    

  • 最佳答案

    这是一个 2.0 选项...

    XML 输入

    <root>
      <Entry>
        <Title>Title B</Title>
        <Year>2010</Year>
      </Entry>
      <Entry>
        <Title>Title A</Title>
        <Year>2010</Year>
      </Entry>
      <Entry>
        <Title>Title B</Title>
        <Year>2012</Year>
      </Entry>
      <Entry>
        <Title>Title A</Title>
        <Year>2011</Year>
      </Entry>
      <Entry>
        <Title>Title A</Title>
        <Year>2012</Year>
      </Entry>
    </root>
    

    XSLT 2.0

    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output indent="yes"/>
      <xsl:strip-space elements="*"/>
    
      <xsl:template match="root">
        <html>
          <xsl:for-each-group select="Entry" group-by="Year">
            <xsl:sort select="Year" data-type="number" order="descending"/>
            <p><xsl:value-of select="Year"/></p>
            <ol>
              <xsl:apply-templates select="current-group()/Title">
                <xsl:sort select="." data-type="text" order="ascending"/>
              </xsl:apply-templates>
            </ol>
          </xsl:for-each-group>
        </html>
      </xsl:template>
    
      <xsl:template match="Title">
        <li><xsl:value-of select="."/></li>
      </xsl:template>
    
    </xsl:stylesheet>
    

    HTML 输出(代码)

    <html>
       <p>2012</p>
       <ol>
          <li>Title A</li>
          <li>Title B</li>
       </ol>
       <p>2011</p>
       <ol>
          <li>Title A</li>
       </ol>
       <p>2010</p>
       <ol>
          <li>Title A</li>
          <li>Title B</li>
       </ol>
    </html>
    

    HTML 输出(显示)

    2012

    1. 标题A
    2. 标题B

    2011

    1. 标题A

    2010

    1. 标题A
    2. 标题B

    关于xml - XSLT 按子元素排序和分组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9703927/

    有关xml - XSLT 按子元素排序和分组的更多相关文章

    1. ruby-on-rails - 按天对 Mongoid 对象进行分组 - 2

      在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev

    2. ruby-on-rails - 如何从 format.xml 中删除 <hash></hash> - 2

      我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为

    3. ruby - 在 Ruby 中创建按公共(public)键值分组的新哈希 - 2

      假设我有一个在Ruby中看起来像这样的哈希:{:ie0=>"Hi",:ex0=>"Hey",:eg0=>"Howdy",:ie1=>"Hello",:ex1=>"Greetings",:eg1=>"Goodday"}有什么好的方法可以将它变成如下内容:{"0"=>{"ie"=>"Hi","ex"=>"Hey","eg"=>"Howdy"},"1"=>{"ie"=>"Hello","ex"=>"Greetings","eg"=>"Goodday"}} 最佳答案 您要求一个好的方法来做到这一点,所以答案是:一种您或同事可以在六个月后理解

    4. ruby-on-rails - 需要帮助最大化多个相似对象中的 3 个因素并适当排序 - 2

      我需要用任何语言编写一个算法,根据3个因素对数组进行排序。我以度假村为例(如Hipmunk)。假设我想去度假。我想要最便宜的地方、最好的评论和最多的景点。但是,显然我找不到在所有3个中都排名第一的方法。Example(assumingthereare20importantattractions):ResortA:$150/night...98/100infavorablereviews...18of20attractionsResortB:$99/night...85/100infavorablereviews...12of20attractionsResortC:$120/night

    5. ruby-on-rails - 在具有 ActiveRecord 条件的相关模型中按字段排序 - 2

      我正在尝试按Rails相关模型中的字段进行排序。我研究的所有解决方案都没有解决如果相关模型被另一个参数过滤?元素模型classItem相关模型:classPriority我正在使用where子句检索项目:@items=Item.where('company_id=?andapproved=?',@company.id,true).all我需要按相关表格中的“位置”列进行排序。问题在于,在优先级模型中,一个项目可能会被多家公司列出。因此,这些职位取决于他们拥有的company_id。当我显示项目时,它是针对一个公司的,按公司内的职位排序。完成此任务的正确方法是什么?感谢您的帮助。PS-我

    6. ruby - 按数字(从大到大)然后按字母(字母顺序)对对象集合进行排序 - 2

      我正在构建一个小部件来显示奥运会的奖牌数。我有一个“国家”对象的集合,其中每个对象都有一个“名称”属性,以及奖牌计数的“金”、“银”、“铜”。列表应该排序:1.首先是奖牌总数2.如果奖牌相同,按类型分割(金>银>铜,即2金>1金+1银)3.如果奖牌和类型相同,则按字母顺序子排序我正在用ruby​​做这件事,但我想语言并不重要。我确实找到了一个解决方案,但如果感觉必须有更优雅的方法来实现它。这是我做的:使用加权奖牌总数创建一个虚拟属性。因此,如果他们有2个金牌和1个银牌,加权总数将为“3.020100”。1金1银1铜为“3.010101”由于我们希望将奖牌数排序为最高的,因此列表按降序排

    7. ruby-on-rails - 在不重新查询数据库的情况下重新排序 Rails 中的事件记录? - 2

      例如,假设我有一个名为Products的模型,并且在ProductsController中,我有以下代码用于product_listView以显示已排序的产品。@products=Product.order(params[:order_by])让我们想象一下,在product_listView中,用户可以使用下拉菜单按价格、评级、重量等进行排序。数据库中的产品不会经常更改。我很难理解的是,每次用户选择新的order_by过滤器时,rails是否必须查询,或者rails是否能够以某种方式缓存事件记录以在服务器端重新排序?有没有一种方法可以编写它,以便在用户排序时rails不会重新查询结果

    8. arrays - 如何在下面的示例中将两个值数组分组为 n 个值数组? - 2

      我已经有很多两个值数组,例如下面的例子ary=[[1,2],[2,3],[1,3],[4,5],[5,6],[4,7],[7,8],[4,8]]我想把它们分组到[1,2,3],[4,5],[5,6],[4,7,8]因为意思是1和2有关系,2和3有关系,1和3有关系,所以1,2,3都有关系我如何通过ruby​​库或任何算法来做到这一点? 最佳答案 这是基本Bron–Kerboschalgorithm的Ruby实现:classGraphdefinitialize(edges)@edges=edgesenddeffind_maximum_

    9. ruby - 如何将相同的相邻数字分组 - 2

      如果至少有两个相邻的数字相同,格式为,我需要打包.这是我的输入:[2,2,2,3,4,3,3,2,4,4,5]以及预期的输出:"2:3,3,4,3:2,2,4:2,5"到目前为止我试过:a=[1,1,1,2,2,3,2,3,4,4,5]a.each_cons(2).any?do|s,t|ifs==t如果相等,也许可以尝试计数器,但那是行不通的。 最佳答案 您可以使用Enumerable#chunk_while(如果你使用的是Ruby>=2.3):a.chunk_while{|a,b|a==b}.flat_map{|chunk|chu

    10. ruby-on-rails - 如何对对象数组进行排序? - 2

      我有一个对象如下:[{:id=>2,:fname=>"Ron",:lname=>"XXXXX",:photo=>"XXX"},{:id=>3,:fname=>"Dain",:lname=>"XXXX",:photo=>"XXXXXXX"},{:id=>1,:fname=>"Bob",:lname=>"XXXXXX",:photo=>"XXXX"}]我想按fname排序,不区分大小写,所以它会导致编号:1,3,2我该如何排序?我正在尝试:@people.sort!{|x,y|y[:fname]x[:fname]}但这没有任何效果。 最佳答案

    随机推荐