XSLT 按 2 个参数排序并按第一个唯一的和第二个最高的选择

XSLT sorting by 2 parametres and choosing by the 1st unique and the 2nd highest

我有一本 xls 书保存为 xml。我有第一行 header 和其他行的数据。 在 xml 中它看起来是:

<Row ss:AutoFitHeight="0">
    <Cell><Data ss:Type="String">Header 1 - id</Data><NamedCell
      ss:Name="_FilterDatabase"/></Cell>
    <Cell><Data ss:Type="String">Header 2 - Version</Data><NamedCell ss:Name="_FilterDatabase"/></Cell>
    <Cell><Data ss:Type="String">Header 3 - some data...</Data><NamedCell
      ss:Name="_FilterDatabase"/></Cell>
</Row>
<Row ss:AutoFitHeight="0">
    <Cell><Data ss:Type="String">id001</Data><NamedCell
      ss:Name="_FilterDatabase"/></Cell>
    <Cell><Data ss:Type="Number">1</Data><NamedCell ss:Name="_FilterDatabase"/></Cell>
    <Cell><Data ss:Type="String">blabla</Data><NamedCell
      ss:Name="_FilterDatabase"/></Cell>        
</Row>
<Row ss:AutoFitHeight="0">
    <Cell><Data ss:Type="String">id001</Data><NamedCell
      ss:Name="_FilterDatabase"/></Cell>
    <Cell><Data ss:Type="Number">2</Data><NamedCell ss:Name="_FilterDatabase"/></Cell>
    <Cell><Data ss:Type="String">blabla</Data><NamedCell
      ss:Name="_FilterDatabase"/></Cell>        
</Row>
<Row ss:AutoFitHeight="0">
    <Cell><Data ss:Type="String">id002</Data><NamedCell
      ss:Name="_FilterDatabase"/></Cell>
    <Cell><Data ss:Type="Number">1</Data><NamedCell ss:Name="_FilterDatabase"/></Cell>
    <Cell><Data ss:Type="String">blabla</Data><NamedCell
      ss:Name="_FilterDatabase"/></Cell>        
</Row>

所以我有两个主要字段 - Header 1 和 Header 2,第一个包含 id(不是唯一的!!!)第二个 - 版本或版本。
在 Excel:

中看起来如何
Number  Version
A001    1
A001    6
A002    2
A002    3
A003    1

我需要使用最大版本处理所有唯一 ID! 在这里我想得到

A001    6
A002    3
A003    1

我的 xslt 代码是:

 <xsl:template match="orig:Table" name ="Table">
    <xsl:variable name="Id" select ="'Number'"/>
    <xsl:element name="Declarations">
      <xsl:for-each select="orig:Row">
        <xsl:sort select="orig:Cell[1]/orig:Data" data-type="text" order="ascending"/>
        <xsl:sort select="orig:Cell[2]/orig:Data" data-type="number" order="descending"/>
        <xsl:if test="$Id!=orig:Cell[1]/orig:Data">
          <xsl:call-template name="Row"> <!--Here in template "Row" all further processing will be done-->
        </xsl:if>

      </xsl:for-each>
    </xsl:element>
  </xsl:template>

起初我对它们进行排序以获得如下列表:

Number  Version
A001    6
A001    1
A002    3
A002    2
A003    1

然后我想保存每个第一个 header 值并在下一行中将它与自身进行比较 - 如果值相同,则意味着它与旧版本的记录相同,我们跳过它.但是如果值发生变化——这意味着我们有一个最高版本的新记录,我们应该接受它。 例如:

"Number" != A001    6 => we take this
A001 = A001 1 => skip
A001 != A002     3 => we take this
and so on

如果我能像

一样使用内部"IF"构造就容易了
variable name="Id" := orig:Cell[1]/orig:Data

但是这里是不可能的!

请帮忙!

这基本上是一个分组问题 - 您正在尝试按第一个单元格值对行进行分组,然后生成一个输出行每组 来自该组中的最新版本。 XSLT 1.0 中的标准方法称为 Muenchian 分组,涉及定义一个 key 来对相关节点进行分组,然后使用 generate-id 的技巧仅拉出每组中的第一个节点:

 <xsl:key name="rowById" match="orig:Row" use="orig:Cell[1]/orig:Data" />

 <xsl:template match="orig:Table" name ="Table">
    <xsl:variable name="Id" select ="'Number'"/>
    <xsl:element name="Declarations">
      <!-- Muenchian grouping - one "iteration" per unique idNNN value -->
      <xsl:for-each select="orig:Row[
           generate-id() = generate-id(key('rowById', orig:Cell[1]/orig:Data)[1])]">
        <!-- sort groups by ID -->
        <xsl:sort select="orig:Cell[1]/orig:Data" data-type="text" order="ascending"/>

        <!-- for-each over the members of this group -->
        <xsl:for-each select="key('rowById', orig:Cell[1]/orig:Data)">
          <!-- find the maximum version value within this group -->
          <xsl:sort select="orig:Cell[2]/orig:Data" data-type="number" order="descending"/>
          <xsl:if test="position() = 1">
            <xsl:call-template name="Row"> <!--Here in template "Row" all further processing will be done-->
          </xsl:if>
        </xsl:for-each>
      </xsl:for-each>
    </xsl:element>
  </xsl:template>