我可以在不使用键的情况下编写一个非常糟糕的xslt,但它非常慢而且很混乱。有谁知道如何将以下XML文件干净地转换为预期的结果?谢谢!
输入:
<testExecution>
<test>
<test.1/>
<test.2/>
<test.3/>
</test>
<comment>
<comment.1/>
<comment.2/>
<comment.3/>
</comment>
<executor>
<executor.1/>
<executor.2/>
<executor.3/>
</executor>
<comment>
<comment.1/>
<comment.2/>
<comment.3/>
</comment>
<comment>
<comment.1/>
<comment.2/>
<comment.3/>
</comment>
<invoker>
<invoker.1/>
<invoker.2/>
<invoker.3/>
</invoker>
<recipient>
<recipient.1/>
<recipient.2/>
<recipient.3/>
</recipient>
<comment>
<comment.1/>
<comment.2/>
<comment.3/>
</comment>
<comment>
<comment.1/>
<comment.2/>
<comment.3/>
</comment>
</testExecution>
结果:
<testExecution>
<test>
<test.1/>
<test.2/>
<test.3/>
</test>
<comment>
<comment.1/>
<comment.2/>
<comment.3/>
</comment>
<people>
<importantPeople>
<executor>
<executor.1/>
<executor.2/>
<executor.3/>
</executor>
<comment>
<comment.1/>
<comment.2/>
<comment.3/>
</comment>
<comment>
<comment.1/>
<comment.2/>
<comment.3/>
</comment>
</importantPeople>
<invoker>
<invoker.1/>
<invoker.2/>
<invoker.3/>
</invoker>
</people>
<recipient>
<recipient.1/>
<recipient.2/>
<recipient.3/>
</recipient>
<comment>
<comment.1/>
<comment.2/>
<comment.3/>
</comment>
<comment>
<comment.1/>
<comment.2/>
<comment.3/>
</comment>
</testExecution>
答案 0 :(得分:4)
此样式表:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="kElementByTest" match="invoker|recipient"
use="generate-id(preceding-sibling::test[1])"/>
<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()[1]|@*"/>
</xsl:copy>
<xsl:apply-templates select="following-sibling::node()[1]"/>
</xsl:template>
<xsl:template match="executor">
<xsl:variable name="vFollowing"
select="key('kElementByTest',
generate-id(preceding-sibling::test[1]))"/>
<people>
<importantPeople>
<xsl:call-template name="identity"/>
</importantPeople>
<xsl:apply-templates select="$vFollowing/self::invoker"
mode="copy"/>
</people>
<xsl:apply-templates select="$vFollowing/self::recipient"
mode="copy"/>
</xsl:template>
<xsl:template match="invoker"/>
<xsl:template match="recipient"/>
<xsl:template match="node()" mode="copy">
<xsl:call-template name="identity"/>
</xsl:template>
</xsl:stylesheet>
输出:
<testExecution>
<test>
<test.1></test.1>
<test.2></test.2>
<test.3></test.3>
</test>
<comment>
<comment.1></comment.1>
<comment.2></comment.2>
<comment.3></comment.3>
</comment>
<people>
<importantPeople>
<executor>
<executor.1></executor.1>
<executor.2></executor.2>
<executor.3></executor.3>
</executor>
<comment>
<comment.1></comment.1>
<comment.2></comment.2>
<comment.3></comment.3>
</comment>
<comment>
<comment.1></comment.1>
<comment.2></comment.2>
<comment.3></comment.3>
</comment>
</importantPeople>
<invoker>
<invoker.1></invoker.1>
<invoker.2></invoker.2>
<invoker.3></invoker.3>
</invoker>
</people>
<recipient>
<recipient.1></recipient.1>
<recipient.2></recipient.2>
<recipient.3></recipient.3>
</recipient>
<comment>
<comment.1></comment.1>
<comment.2></comment.2>
<comment.3></comment.3>
</comment>
<comment>
<comment.1></comment.1>
<comment.2></comment.2>
<comment.3></comment.3>
</comment>
</testExecution>
注意:细粒度遍历。 “仅适用于此测试”的关键字如下。用于“关闭此级别”的空模板。推送方式“保持处理”。它可以是完全的“拉式”匹配“标记之前的流行”。
答案 1 :(得分:1)
此转换使用并覆盖标识规则。使用executor
函数检索key()
后面的注释。紧接executor
之后的invoker
,comment
和executor
将被复制到名为people
的特殊模式中。在通常的匿名模式下,这些模板与空模板匹配,以避免再次复制它们:
<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="kExecComments" match=
"comment
[preceding-sibling::*
[not(self::comment)][1]
[self::executor]
]"
use="generate-id(preceding-sibling::executor[1])"/>
<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="executor">
<people>
<importantPeople>
<xsl:apply-templates mode="people"
select=".|key('kExecComments', generate-id())"/>
</importantPeople>
<xsl:apply-templates mode="people" select=
"following-sibling::invoker"/>
</people>
</xsl:template>
<xsl:template match="executor|comment|invoker"
mode="people">
<xsl:call-template name="identity"/>
</xsl:template>
<xsl:template match=
"invoker |
comment
[preceding-sibling::*
[not(self::comment)][1]
[self::executor]
]"/>
</xsl:stylesheet>
应用于提供的XML文档:
<testExecution>
<test>
<test.1/>
<test.2/>
<test.3/>
</test>
<comment>
<comment.1/>
<comment.2/>
<comment.3/>
</comment>
<executor>
<executor.1/>
<executor.2/>
<executor.3/>
</executor>
<comment>
<comment.1/>
<comment.2/>
<comment.3/>
</comment>
<comment>
<comment.1/>
<comment.2/>
<comment.3/>
</comment>
<invoker>
<invoker.1/>
<invoker.2/>
<invoker.3/>
</invoker>
<recipient>
<recipient.1/>
<recipient.2/>
<recipient.3/>
</recipient>
<comment>
<comment.1/>
<comment.2/>
<comment.3/>
</comment>
<comment>
<comment.1/>
<comment.2/>
<comment.3/>
</comment>
</testExecution>
生成想要的正确结果:
<testExecution>
<test>
<test.1/>
<test.2/>
<test.3/>
</test>
<comment>
<comment.1/>
<comment.2/>
<comment.3/>
</comment>
<people>
<importantPeople>
<executor>
<executor.1/>
<executor.2/>
<executor.3/>
</executor>
<comment>
<comment.1/>
<comment.2/>
<comment.3/>
</comment>
<comment>
<comment.1/>
<comment.2/>
<comment.3/>
</comment>
</importantPeople>
<invoker>
<invoker.1/>
<invoker.2/>
<invoker.3/>
</invoker>
</people>
<recipient>
<recipient.1/>
<recipient.2/>
<recipient.3/>
</recipient>
<comment>
<comment.1/>
<comment.2/>
<comment.3/>
</comment>
<comment>
<comment.1/>
<comment.2/>
<comment.3/>
</comment>
</testExecution>