XSLT Grouping问题:如何为连续class=list的p元素添加父节点
问题原因
你当前使用group-by的分组逻辑会将所有满足@class='list'的节点合并为同一组,不考虑节点的相邻关系,中间间隔的普通段落不会拆分列表,导致所有列表段落被打包到同一个<list>标签中,和预期不符。同时原模板没有保留原<section>标签的输出逻辑,导致外层标签丢失。
正确实现方案
针对连续相邻节点分组的需求,使用XSLT 2.0及以上版本支持的group-adjacent分组语法即可实现,该语法会按照节点的先后顺序,将连续相邻且分组key相同的节点划分为同一组,完全匹配你的需求。
修正后的XSLT代码
<xsl:template match="section"> <!-- 保留原section节点输出 <section> <xsl:for-each-group select="node()" group-adjacent="if (self::p[@class='list']) then 'list' else 'nolist'"> <xsl:choose> <xsl:when test="current-grouping-key() = 'list'"> <list> <xsl:apply-templates select="current-group()" /> </list> </xsl:when> <xsl:otherwise> <xsl:apply-templates select="current-group()" /> </xsl:otherwise> </xsl:choose> </xsl:for-each-group> </section> </xsl:template> <!-- 其余节点默认复制即可 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template>
补充说明
如果使用XSLT 1.0环境,没有group-adjacent语法支持,可以通过递归遍历子节点的方式实现相邻分组,逻辑如下:
- 遍历第一个子节点,判断是否为列表段落:
- 如果是,则找到后续相邻的所有列表段落打包为一组,输出
<list>标签包裹 - 如果不是,直接输出该节点,继续遍历下一个节点
- 如果是,则找到后续相邻的所有列表段落打包为一组,输出
内容的提问来源于stack exchange,提问作者Jason
相关产品推荐
相关产品推荐

