我有一组必须包含在新元素中的顺序节点。例子:
<root>
<c>cccc</c>
<a gr="g1">aaaa</a> <b gr="g1">1111</b>
<a gr="g2">bbbb</a> <b gr="g2">2222</b>
</root>
必须包含在fold
标签,结果(在 XSLT 之后):
<root>
<c>cccc</c>
<fold><a gr="g1">aaaa</a> <b gr="g1">1111</b></fold>
<fold><a gr="g2">bbbb</a> <b gr="g2">2222</b></fold>
</root>
所以,我有一个“分组标签”(@gr
)但无法想象如何生成正确的折叠标签。
我正在尝试使用以下线索这个问题, or 另一个...但是我有一个“分组标签”,所以我知道我的解决方案不需要使用key()
功能。
我的非通用解决方案是:
<xsl:template match="/">
<root>
<xsl:copy-of select="root/c"/>
<fold><xsl:for-each select="//*[@gr='g1']">
<xsl:copy-of select="."/>
</xsl:for-each></fold>
<fold><xsl:for-each select="//*[@gr='g2']">
<xsl:copy-of select="."/>
</xsl:for-each></fold>
</root>
</xsl:template>
我需要一个通用的解决方案(!),循环所有 @gr 并应对(身份)所有没有 @gr 的上下文...也许使用身份转变.
另一个(未来的)问题是通过折叠的折叠来递归地执行此操作。
在 XSLT 1.0 中,处理此类事情的标准技术称为 Muenchian 分组,并且涉及使用key定义节点应如何分组以及使用的技巧generate-id
仅提取每个组中的第一个节点作为整个组的代理。
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:strip-space elements="*" />
<xsl:output indent="yes" />
<xsl:key name="elementsByGr" match="*[@gr]" use="@gr" />
<xsl:template match="@*|node()" name="identity">
<xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy>
</xsl:template>
<!-- match the first element with each @gr value -->
<xsl:template match="*[@gr][generate-id() =
generate-id(key('elementsByGr', @gr)[1])]" priority="2">
<fold>
<xsl:for-each select="key('elementsByGr', @gr)">
<xsl:call-template name="identity" />
</xsl:for-each>
</fold>
</xsl:template>
<!-- ignore subsequent ones in template matching, they're handled within
the first element template -->
<xsl:template match="*[@gr]" priority="1" />
</xsl:stylesheet>
这实现了您想要的分组,但就像您的非通用解决方案一样,它不会保留缩进和之间的空白文本节点a
and b
元素,即它会给你
<root>
<c>cccc</c>
<fold>
<a gr="g1">aaaa</a>
<b gr="g1">1111</b>
</fold>
<fold>
<a gr="g2">bbbb</a>
<b gr="g2">2222</b>
</fold>
</root>
请注意,如果您能够使用 XSLT 2.0,那么整个事情就变成了一个for-each-group
:
<xsl:template match="root">
<xsl:for-each-group select="*" group-adjacent="@gr">
<xsl:choose>
<!-- wrap each group in a fold -->
<xsl:when test="@gr">
<fold><xsl:copy-of select="current-group()" /></fold>
</xsl:when>
<!-- or just copy as-is for elements that don't have a @gr -->
<xsl:otherwise>
<xsl:copy-of select="current-group()" />
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:template>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)