0

我有一个包含关系列表的 xml 文件。样本:

<document>
  <list>
    <rel>
       <item1>1</item1>
       <item2>6</item2>
    </rel>
    <rel>
       <item1>2</item1>
       <item2>3</item2>
    </rel>
    <rel>
       <item1>3</item1>
       <item2>5</item2>
    </rel>
    <rel>
       <item1>3</item1>
       <item2>6</item2>
    </rel>
    <rel>
       <item1>2</item1>
       <item2>8</item2>
    </rel>
    <rel>
       <item1>2</item1>
       <item2>7</item2>
    </rel>
 </list>
</document>  

item1 表示项目的 id。

我想打印出第 n 个 id 的列表,按它们在 item1 中的出现次数降序排列。所以我需要计算每个 id 在 item1 中出现的次数,然后按降序对它们进行排序。最后,我需要打印第 n 个 id。

预期答案:

2
3

我正在使用的 xlst 代码是:

       <body>
            <ul>
             <xsl:for-each select="document/list/rel">
                 <xsl:sort select="count(item1)" order="descending"/>
                 <xsl:if test="position() &lt;= $nthIDs">
                    <li><xsl:value-of select="item1"/></li>
                 </xsl:if>
             </xsl:for-each>
            </ul>
        </body>

代码返回什么:

1
2

它所做的只是打印第 n 个第一个 item1 而不进行任何排序,因此它不能按预期工作。我的代码如果主要基于:xslt 按子元素计数排序 ,但是那个使用直接子节点,我需要孙节点。我找到了另一个链接:XSLT 对孙子节点进行排序并选择另一个 谈论孙子的孙子的值,但我不完全理解这种排序是如何工作的。有人可以帮我理解第二个链接中使用的排序以及如何实现它吗?

我正在使用 xslt 3.0,但 2.0 或 1.0 中的任何解决方案都非常受欢迎。

谢谢你。

4

1 回答 1

1

您可以使用分组for-each-group,然后计算组中的项目数并按它们排序,如果需要仅输出多个组:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    expand-text="yes"
    version="3.0">

  <xsl:param name="number-of-groups" as="xs:integer" select="2"/>

  <xsl:mode on-no-match="shallow-skip"/>

  <xsl:output method="html" indent="yes" html-version="5"/>

  <xsl:template match="/">
    <html>
      <head>
        <title>Group and Sort</title>
      </head>
      <body>
          <xsl:apply-templates/>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="list">
      <ul>
          <xsl:for-each-group select="rel" group-by="item1">
              <xsl:sort select="count(current-group())" order="descending"/>
              <xsl:if test="position() le $number-of-groups">
                  <li>
                      item {item1}, count: {count(current-group())}
                  </li>
              </xsl:if>
          </xsl:for-each-group>
      </ul>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/bFukv8p

于 2018-03-10T08:16:36.987 回答