我想根据一些变量选择节点。 XML代码:
<data>
<prot seq="AAA">
<node num="1">1345</node>
<node num="1">11245</node>
<node num="2">88885</node>
</prot>
<prot seq="BBB">
<node num="1">678</node>
<node num="1">456</node>
<node num="2">6666</node>
</prot>
<prot seq="CCC">
<node num="1">111</node>
<node num="1">222</node>
<node num="2">333</node>
</prot>
</data>
我想要的XML
<output>
<prot seq="AAA">
<node num="1">1345</node>
<node num="2">88885</node>
</prot>
<prot seq="BBB">
<node num="1">678</node>
<node num="2">6666</node>
</prot>
<prot seq="CCC">
<node num="1">111</node>
<node num="2">333</node>
</prot>
</data>
所以,我的想法是用一个xsl:key元素对节点进行分组,然后为每个节点做一个for-each。例如:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:key name="by" match="/data/prot" use="concat(@seq,'|',node/@num)"/>
<xsl:template match="/">
<root>
<xsl:apply-templates select="/data/prot"/>
</root>
</xsl:template>
<xsl:template match="/data/prot">
<xsl:for-each select="./node">
<xsl:for-each select="key('by',concat(current()/../@seq,'|',current()/@num))">
node <xsl:value-of select="./node" />
</xsl:for-each>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
但输出不是我的预期,我看不出我做错了什么。我宁愿保留for-each结构。就好像我没有正确使用xsl:key分组功能一样。
我得到的输出,不需要的
<root>
node 1345
node 1345
node 678
node 678
node 111
node 111</root>
要测试的代码 http://www.xsltcake.com/slices/sgWUFu/20
谢谢!
答案 0 :(得分:2)
您的代码中的主要问题是键索引prot
元素,但我们想要去重复(并且需要索引)的是node
元素
这是一个简短而正确的解决方案:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="nodeByParentAndNum" match="node"
use="concat(generate-id(..), '+', @num)"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*">
<data>
<xsl:apply-templates/>
</data>
</xsl:template>
<xsl:template match=
"node
[not(generate-id()
=
generate-id(key('nodeByParentAndNum',
concat(generate-id(..), '+', @num)
)
[1]
)
)
]
"/>
</xsl:stylesheet>
将此转换应用于提供的XML文档:
<data>
<prot seq="AAA">
<node num="1">1345</node>
<node num="1">11245</node>
<node num="2">88885</node>
</prot>
<prot seq="BBB">
<node num="1">678</node>
<node num="1">456</node>
<node num="2">6666</node>
</prot>
<prot seq="CCC">
<node num="1">111</node>
<node num="1">222</node>
<node num="2">333</node>
</prot>
</data>
产生了想要的正确结果:
<data>
<prot seq="AAA">
<node num="1">1345</node>
<node num="2">88885</node>
</prot>
<prot seq="BBB">
<node num="1">678</node>
<node num="2">6666</node>
</prot>
<prot seq="CCC">
<node num="1">111</node>
<node num="2">333</node>
</prot>
</data>