它可以像这样简短而简单(无需多次调用模板,,,xsl:for-each
)xsl:if
。这是完整的转换:
<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="kFollowing" match="*/*[not(self::row)]"
use="concat(generate-id(..), '+',
generate-id(preceding-sibling::row[1])
)"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template priority="2" match=
"*/*[not(self::row)
and
(preceding-sibling::*[1][self::row]
or not(preceding-sibling::*)
)]">
<notRow>
<xsl:copy-of select=
"key('kFollowing', concat(generate-id(..), '+',
generate-id(preceding-sibling::row[1])
))"/>
</notRow>
</xsl:template>
<xsl:template match="*/*[not(self::row)]"/>
</xsl:stylesheet>
当此转换应用于提供的 XML 时(包装到单个顶部元素中以使其格式正确):
<t>
<h />
<row id='v' />
<a />
<b />
<row id='w' />
<d />
<row id='x' />
<row id='y' />
<f />
<r />
<row id='z' />
</t>
产生了想要的正确结果:
<t>
<notRow>
<h/>
</notRow>
<row id="v"/>
<notRow>
<a/>
<b/>
</notRow>
<row id="w"/>
<notRow>
<d/>
</notRow>
<row id="x"/>
<row id="y"/>
<notRow>
<f/>
<r/>
</notRow>
<row id="z"/>
</t>
更新:
OP 已经表达了一个额外的要求,即节点需要通过匹配的模板来处理——而不仅仅是复制。
这只需要最小的改变:
<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="kFollowing" match="*/*[not(self::row)]"
use="concat(generate-id(..), '+',
generate-id(preceding-sibling::row[1])
)"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template priority="2" match=
"*/*[not(self::row)
and
(preceding-sibling::*[1][self::row]
or not(preceding-sibling::*)
)]">
<notRow>
<xsl:apply-templates mode="group" select=
"key('kFollowing', concat(generate-id(..), '+',
generate-id(preceding-sibling::row[1])
))"/>
</notRow>
</xsl:template>
<!-- This template can be replaced with whatever processing needed -->
<xsl:template match="*" mode="group">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="*/*[not(self::row)]"/>
</xsl:stylesheet>
在“组”模式下操作的模板应替换为实现所需处理的模板。在这种情况下,它会复制匹配的元素——但在实际应用程序中,任何想要的处理都会在这里进行。