我将xls书保存为xml。我有第一行标题和其他行数据。 在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>
所以我有两个主要字段 - 标题1和标题2,第一个包含id(不唯一!!!)第二个版本或版本。
它在Excel中看起来如何:
Number Version
A001 1
A001 6
A002 2
A002 3
A003 1
我需要使用最高版本处理所有唯一身份证件! 在这里,我想得到
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
然后我想保存每个第一个标头值并在下一行中将它与自身进行比较 - 如果值相同,则表示它与旧版本的记录相同,我们跳过它。但是如果价值发生变化 - 这意味着我们有一个最新版本的新记录,我们应该接受它。 例如:
"Number" != A001 6 => we take this
A001 = A001 1 => skip
A001 != A002 3 => we take this
and so on
如果我可以使用内部&#34; IF&#34;那将会很容易。建设如
variable name="Id" := orig:Cell[1]/orig:Data
但这里不可能!
请帮助!
答案 0 :(得分:0)
这基本上是一个分组问题 - 您尝试按行的第一个单元格值对行进行分组,然后从该组中的最新版本生成一个每组的输出行 。 XSLT 1.0中的标准方法称为 Muenchian分组,它涉及定义一个密钥,它将相关节点分组,然后使用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>