下面是一个示例:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:functx="http://www.functx.com"
xmlns:mf="http://example.com/mf"
exclude-result-prefixes="xs functx">
<xsl:output indent="yes"/>
<xsl:function name="functx:index-of-node" as="xs:integer*">
<xsl:param name="nodes" as="node()*"/>
<xsl:param name="nodeToFind" as="node()"/>
<xsl:sequence select="
for $seq in (1 to count($nodes))
return $seq[$nodes[$seq] is $nodeToFind]
"/>
</xsl:function>
<xsl:function name="mf:eliminate-deep-equal-duplicates" as="node()*">
<xsl:param name="nodes"/>
<xsl:sequence
select="for $node in $nodes
return $node[not(some $preceding-node in $nodes[position() lt functx:index-of-node($nodes, $node)] satisfies deep-equal($node, $preceding-node))]"/>
</xsl:function>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* , node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="coll">
<xsl:copy>
<xsl:for-each-group select="rootNode" group-by="Header/code">
<xsl:copy>
<xsl:apply-templates select="Header,
mf:eliminate-deep-equal-duplicates(current-group()/(* except (Header, children))),
children"/>
</xsl:copy>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
<xsl:template match="rootNode/children">
<xsl:copy>
<xsl:apply-templates select="mf:eliminate-deep-equal-duplicates(current-group()/children/*)"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
关于一个解释:发布的样式表有三个模板,第一个是身份转换模板(它允许我们复制我们想要复制的元素
apply-templates
在其他模板中),第二个匹配
coll
元素创建它们的浅副本,然后应用文本书
for-each-group
在
rootNode
元素,按其分组
Header/code
,正如你所要求的。在
对于每组
,对于每组
xsl:copy
创建一个
根节点
并通过处理
Header
元素(所以我们只得到一个
收割台
每组中的result元素),除
收割台
和
children
组中没有前一个项目的每个项目
deep-equals
组中的元素和
儿童
元素,以确保每个组都获得
儿童
子元素。在该元素的模板中,我们需要确保处理当前组中没有
deep-equal
在它们之前复制。
我已将长表达式重构为函数
mf:eliminate-deep-equal-duplicates
,它选择节点序列中没有相同序列中的前一个节点的那些节点
深度相等
.
该解决方案利用了函数
http://www.xsltfunctions.com/xsl/functx_index-of-node.html
functx库的索引,它为我们提供了序列中节点的索引。
正如弗拉基米尔·内斯特罗夫斯基在评论中指出的
mf:消除深度相等重复
也可以在不使用functx的情况下实现
functx:index-of-node
:
<xsl:function name="mf:eliminate-deep-equal-duplicates" as="node()*">
<xsl:param name="nodes"/>
<xsl:sequence
select="for $i in (1 to count($nodes)),
$node in $nodes[$i]
return $node[not(some $preceding-node in $nodes[position() lt $i] satisfies deep-equal($node, $preceding-node))]"/>
</xsl:function>