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>
我有一本 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>