相等的节点应该在单个计数器元素下。 输入:
<Move-Afile>
<Afile>
<Item>
<PACK050>
<PackNumber>1234</PackNumber>
</PACK050>
</Item>
<Item>
<PACK050>
<PackNumber>567</PackNumber>
</PACK050>
</Item>
<Item>
<PACK050>
<PackNumber>567</PackNumber>
</PACK050>
</Item>
<Item>
<PACK050>
<PackNumber>126</PackNumber>
</PACK050>
</Item>
<Item>
<PACK050>
<PackNumber>567</PackNumber>
</PACK050>
</Item>
</Afile>
</Move-Afile>
对于每个包号,我们需要递增计数器变量,但是这里存在一个条件,如果previous等于current,我们必须忽略计数器(不需要递增),如下面的output.all等于节点来自一个计数器,如下面的输出。
XSLT模板应该包含<for-each>
,如下面的结构。
<xsl:template match="/">
<A>
<target>
<xsl:for-each select="/Move-Afile/Afile/Item/PACK050/PackNumber">
<xsl:variable name="count">
<!-- get the count here-->
</xsl:variable>
<counter>$count</counter>
<PNumber><xsl:value-of select="."/></PNumber>
</xsl:for-each>
</target>
</A>
</xsl:template>
输出:
<A>
<target>
<Item>
<PACK050>
<counter>1</counter><!-- if previous <PackNumber> is not equal to current <PackNumber> increment the count-->
<PNumber>1234</PNumber>
</PACK050>
</Item>
<Item
<PACK050>
<counter>2</counter><!-- if previous <PackNumber> is not equal to current <PackNumber> increment the count-->
<PNumber>567</PNumber>
</PACK050>
</Item>
<Item><!-- if previous <PackNumber> is equal to current <PackNumber> ignore the counter -->
<PACK050>
<PNumber>567</PNumber>
</PACK050>
</Item>
<Item><!-- if previous <PackNumber> is equal to current <PackNumber> ignore the counter -->
<PACK050>
<PNumber>567</PNumber>
</PACK050>
</Item>
<Item>
<PACK050>
<counter>3</counter><!-- if previous <PackNumber> is not equal to current <PackNumber> increment the count-->
<PNumber>126</PNumber>
</PACK050>
</Item>
</target>
</A>
答案 0 :(得分:3)
不要将其视为递增计数器,将其视为对相似节点进行分组。您在此处尝试执行的操作是按Item
对PackNumber
个元素进行分组,然后为每个组写出第一个匹配的Item
,其值为counter
,其余没有。
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:key name="itemByPnum" match="Item" use="PACK050/PackNumber" />
<xsl:template match="/">
<A>
<target>
<xsl:apply-templates select="Move-Afile/Afile/Item[generate-id() =
generate-id(key('itemByPnum', PACK050/PackNumber)[1])]" />
</target>
</A>
</xsl:template>
<xsl:template match="Item">
<xsl:apply-templates select="." mode="copy">
<xsl:with-param name="counter">
<counter><xsl:value-of select="position()" /></counter>
</xsl:with-param>
</xsl:apply-templates>
<!-- copy without the <counter> all matching Items except the first one -->
<xsl:apply-templates mode="copy"
select="key('itemByPnum', PACK050/PackNumber)
[generate-id() != generate-id(current())]" />
</xsl:template>
<xsl:template match="Item" mode="copy">
<xsl:param name="counter" />
<Item>
<PACK050>
<xsl:copy-of select="$counter" />
<PNumber><xsl:value-of select="PACK050/PackNumber" /></PNumber>
</PACK050>
</Item>
</xsl:template>
</xsl:stylesheet>
这是一种称为Muenchian分组的技术示例。 apply-templates
模板中的初始/
会为每个Item
提取第一个 PackNumber
,Item
模板会生成正确的输出对于那个小组。
答案 1 :(得分:2)
这个问题实际上可以通过使用着名的Muhnchian分组方法来解决XSLT 1.0。
当这个XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kItemByPackNo" match="Item" use="*/PackNumber"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*">
<A>
<target>
<xsl:apply-templates
select="*/Item[generate-id() =
generate-id(key('kItemByPackNo', */PackNumber)[1])]"/>
</target>
</A>
</xsl:template>
<xsl:template match="Item">
<Item>
<counter>
<xsl:value-of select="position()"/>
</counter>
<xsl:apply-templates/>
</Item>
<xsl:copy-of
select="key('kItemByPackNo', */PackNumber)[
not(generate-id() = generate-id(current()))
]"/>
</xsl:template>
<xsl:template match="PackNumber">
<PNumber>
<xsl:apply-templates/>
</PNumber>
</xsl:template>
</xsl:stylesheet>
...适用于提供的XML:
<Move-Afile>
<Afile>
<Item>
<PACK050>
<PackNumber>1234</PackNumber>
</PACK050>
</Item>
<Item>
<PACK050>
<PackNumber>567</PackNumber>
</PACK050>
</Item>
<Item>
<PACK050>
<PackNumber>567</PackNumber>
</PACK050>
</Item>
<Item>
<PACK050>
<PackNumber>126</PackNumber>
</PACK050>
</Item>
<Item>
<PACK050>
<PackNumber>567</PackNumber>
</PACK050>
</Item>
</Afile>
</Move-Afile>
...产生了所需的结果:
<A>
<target>
<Item>
<counter>1</counter>
<PACK050>
<PNumber>1234</PNumber>
</PACK050>
</Item>
<Item>
<counter>2</counter>
<PACK050>
<PNumber>567</PNumber>
</PACK050>
</Item>
<Item>
<PACK050>
<PackNumber>567</PackNumber>
</PACK050>
</Item>
<Item>
<PACK050>
<PackNumber>567</PackNumber>
</PACK050>
</Item>
<Item>
<counter>3</counter>
<PACK050>
<PNumber>126</PNumber>
</PACK050>
</Item>
</target>
</A>