如何使用XSLT将不同class的相邻元素归为同一分组?
解决方案
核心思路
使用XSLT 2.0+的xsl:for-each-group特性,通过自定义分组键将warning、warninglistbullet归为同一组,parts单独成组,其余元素保持原样。关键是通过条件判断生成统一的组标识,而非直接用@class作为分组依据。
输入HTML示例
<body> <p class="warning">Warning text 1</p> <p class="warninglistbullet">Bullet 1</p> <p class="warninglistbullet">Bullet 2</p> <p class="normal">Normal text</p> <div class="parts">Part A</div> <div class="parts">Part B</div> <p class="warning">Another warning</p> </body>
期望输出HTML
<body> <div class="warning-group"> <p class="warning">Warning text 1</p> <p class="warninglistbullet">Bullet 1</p> <p class="warninglistbullet">Bullet 2</p> </div> <p class="normal">Normal text</p> <div class="parts-group"> <div class="parts">Part A</div> <div class="parts">Part B</div> </div> <div class="warning-group"> <p class="warning">Another warning</p> </div> </body>
正确XSLT模板
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 复制所有未匹配的节点(如body标签本身) --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- 匹配body元素,对其子元素进行分组处理 --> <xsl:template match="body"> <xsl:copy> <xsl:for-each-group select="*" group-adjacent=" <!-- 为目标class生成统一分组键 --> if (@class = 'warning' or @class = 'warninglistbullet') then 'warning-group' else if (@class = 'parts') then 'parts-group' else 'other' "> <!-- 处理warning组和parts组:包裹到对应div中 --> <xsl:choose> <xsl:when test="current-grouping-key() = 'warning-group'"> <div class="warning-group"> <xsl:apply-templates select="current-group()"/> </div> </xsl:when> <xsl:when test="current-grouping-key() = 'parts-group'"> <div class="parts-group"> <xsl:apply-templates select="current-group()"/> </div> </xsl:when> <!-- 其他元素直接输出,不分组 --> <xsl:otherwise> <xsl:apply-templates select="current-group()"/> </xsl:otherwise> </xsl:choose> </xsl:for-each-group> </xsl:copy> </xsl:template> </xsl:stylesheet>
关键说明
- 分组逻辑:通过
group-adjacent的条件判断,将warning和warninglistbullet映射到同一个键warning-group,parts映射到parts-group,其余元素为other,确保相邻的目标元素被分到同一组。 - 节点复制:默认模板负责复制所有未被特殊处理的节点(如属性、文本、非目标元素),保证原有结构不受破坏。
- 组处理:对每个分组,根据键值决定是否包裹到新的
<div>中,目标组统一包裹,非目标组直接输出原元素。
内容的提问来源于stack exchange,提问作者Diego Schiavon
相关产品推荐
相关产品推荐

