You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用XSLT group-adjacent实现符合前置节点条件的节点分组?

XML节点分组需求及XSLT修正方案

需求描述

需要将目标XML中的<d>节点以及紧跟在<d>之后的<a>节点归入<GROUP>标签,其余节点保持原有结构不变。

输入XML

<doc>
    <a>blabla</a>
    <b>blabla</b>
    <c>text C</c>
    <d>text D</d>
    <a>bla</a>
    <d>text D</d>
    <a>bla</a>
</doc>

期望输出XML

<doc>
    <a>blabla</a>
    <b>blabla</b>
    <c>text C</c>
<GROUP>
    <d>text D</d>
    <a>bla</a>
    <d>text D</d>
    <a>bla</a>
</GROUP>
</doc>

原代码问题

尝试的XSLT代码会把所有<a>和<d>节点都归为一组,无法排除那些前一个节点不是<d>的<a>节点;同时使用<xsl:value-of>会丢失节点标签结构,只保留文本内容。

原代码:

<xsl:template match="doc">
        <xsl:copy>
            <xsl:for-each-group select="*"
                group-adjacent="boolean(self::a | self::d)">
                <xsl:choose>
                    <xsl:when test="current-grouping-key()">
                        <xsl:element name="GROUP">
                            <xsl:value-of select="current-group()"/>
                        </xsl:element>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:apply-templates select="current-group()"/>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:for-each-group>
        </xsl:copy>
    </xsl:template>

修正后的XSLT代码

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <!-- 处理doc节点 -->
    <xsl:template match="doc">
        <xsl:copy>
            <!-- 输出不需要分组的节点:非d节点,且不是紧跟在d后面的a节点 -->
            <xsl:apply-templates select="*[not(self::d) and not(self::a and preceding-sibling::*[1][self::d])]"/>
            
            <!-- 包裹所有符合分组条件的节点 -->
            <xsl:if test="*[self::d or (self::a and preceding-sibling::*[1][self::d])]">
                <GROUP>
                    <xsl:apply-templates select="*[self::d or (self::a and preceding-sibling::*[1][self::d])]"/>
                </GROUP>
            </xsl:if>
        </xsl:copy>
    </xsl:template>

    <!-- 默认模板:复制所有节点和属性 -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

修正思路说明

  1. 筛选非分组节点:通过条件not(self::d) and not(self::a and preceding-sibling::*[1][self::d]),精准排除需要分组的节点,只输出符合要求的原始节点。
  2. 包裹分组节点:收集所有<d>节点,以及前一个兄弟节点是<d>的<a>节点,统一用<GROUP>标签包裹。
  3. 保留节点结构:使用默认模板复制节点,替代原代码的<xsl:value-of>,确保节点的标签和内容完整保留。

内容的提问来源于stack exchange,提问作者jessika perignon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 13:46:05