【问题标题】:muenchian grouping慕尼黑集团
【发布时间】:2012-01-02 22:52:41
【问题描述】:

我想知道这个谓词([1])如何在 muenchian 分组中始终硬编码为 1。经过大量搜索,我并不清楚这个概念。解释为当前节点,与key返回的第一组进行比较。 为什么它总是与第一个匹配的键进行比较? 另外我们为什么要再次给contact[count(. | key('contacts-by-surname', surname)[1]) = 1], the =1 part? 1 是硬编码的。我参考了以下链接

http://www.jenitennison.com/xslt/grouping/muenchian.html

【问题讨论】:

    标签: xslt muenchian-grouping xslkey


    【解决方案1】:

    假设我们有一个键定义<xsl:key name="contacts-by-surname" match="contact" use="surname"/>,那么表达式key('contacts-by-surname', 'Doe') 为您提供了一个包含所有contact 元素的节点集,其中surnameDoe。表达式key('contacts-by-surname', 'Doe')[1] 为您提供了该“组”中的第一个contact

    现在,当使用for-eachapply-templates 处理所有contact 元素时,我们通常需要一种方法来识别每个组中的第一个contact 元素。这可以通过<xsl:for-each select="contact[count(. | key('contacts-by-surname', surname)[1]) = 1]"><xsl:for-each select="contact[generate-id() = generate-id(key('contacts-by-surname', surname)[1])]"> 来实现。

    如果您的要求不同,例如您想识别每个组中的最后一项,那么您当然可以使用不同的谓词,如<xsl:for-each select="contact[count(. | key('contacts-by-surname', surname)[last()]) = 1]"><xsl:for-each select="contact[generate-id() = generate-id(key('contacts-by-surname', surname)[last()])]">

    【讨论】:

      【解决方案2】:

      我想知道这个谓词([1])是如何硬编码为 1 的 muenchian 集团。

      这很简单

      key() 函数为给定组生成所有节点,我们只想从任何组中获取一个节点。

      不能保证所有组中都会有两个或更多节点——有些可能只有一个节点。

      这就是为什么从每个组中获取第一个(也可能是唯一的)节点是安全和方便的。

      我们同样可以从每个组中取出 last 节点进行分组(但这会降低效率):

      <xsl:stylesheet version="1.0"
       xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
       <xsl:output omit-xml-declaration="yes" indent="yes"/>
       <xsl:strip-space elements="*"/>
      
       <xsl:key name="kNumByMod3" match="num"
        use=". mod 3"/>
      
       <xsl:template match=
        "num[generate-id()
            =
             generate-id(key('kNumByMod3', . mod 3)[last()])
            ]
        ">
      
      
        3k + <xsl:value-of select=". mod 3"/>:
      <xsl:text/>
        <xsl:copy-of select="key('kNumByMod3', . mod 3)"/>
       </xsl:template>
       <xsl:template match="text()"/>
      </xsl:stylesheet>
      

      应用于此 XML 文档时

      <nums>
        <num>01</num>
        <num>02</num>
        <num>03</num>
        <num>04</num>
        <num>05</num>
        <num>06</num>
        <num>07</num>
        <num>08</num>
        <num>09</num>
        <num>10</num>
      </nums>
      

      产生想要的、正确分组的结果

        3k + 2:
      <num>02</num>
      <num>05</num>
      <num>08</num>
      
      
        3k + 0:
      <num>03</num>
      <num>06</num>
      <num>09</num>
      
      
        3k + 1:
      <num>01</num>
      <num>04</num>
      <num>07</num>
      <num>10</num>
      

      【讨论】:

      • 完美。另外通过一些实验发现下面三个做分组 1)contact[count(.|key('contacts-by-surname', surname)[1]) = 1]">2)contact[count(.|key ('联系人-姓氏', 姓氏)[2]) = 1]">3)contact[count(. | key('联系人-姓氏', 姓氏)[last()]) = 1]" >
      • 是的,谓词是测试两个节点是否相同(同一个节点)。这也可以使用 generate-id() 来完成,并且在 XPath 2.0 中使用 is 运算符表示。
      • @user1004770:不客气。如果您对此主题感兴趣,请查看此答案:stackoverflow.com/questions/133092/…
      【解决方案3】:

      基本算法是有两个嵌套循环。外循环从每一组中选择一个代表节点,内循环选择该组中的所有节点(包括被选为代表的节点)。从组中选择一个代表节点的最简单方法是选择第一个,因此谓词[1]

      【讨论】:

      • @_Michael:我的解决方案中有 no 循环,它仍然是 grouping。我认为对于 XSLT 3.0 我们仍然可以提供一个分组功能,它消除了xsl:for-each-group 最明显的缺点——缺乏可组合性..
      猜你喜欢
      • 2013-08-03
      • 2014-08-11
      • 2020-03-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-26
      • 2016-12-13
      相关资源
      最近更新 更多