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

XSL实现:将指定兄弟标签包裹进section标签并避免内容重复

问题原因

你遇到的内容重复问题,本质是同一批后续兄弟元素被输出了两次:

  • 第一次是在<p outputclass="Endofclause">的模板里,你主动调用<xsl:apply-templates select="following-sibling::*"/>把这些元素塞进了<section>;
  • 第二次是因为默认的<xsl:mode on-no-match="shallow-copy"/>会遍历所有未被特殊模板匹配的元素,这些后续兄弟元素又被浅拷贝输出了一遍。
解决办法

核心是让这些后续兄弟元素只被输出一次——要么只在<section>里输出,要么阻止默认模板输出它们。下面给两种实用的修改方案:

方案1:用模板模式区分处理逻辑

给需要包裹进<section>的元素单独定义一个处理模式,同时写一个空模板阻止默认输出这些元素,只有在指定模式下才输出它们:

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    
    <!-- 默认浅拷贝所有未匹配的元素 -->
    <xsl:mode on-no-match="shallow-copy"/>
    
    <!-- 处理Endofclause的p元素 -->
    <xsl:template match="p[@outputclass='Endofclause']">
        <xsl:copy>
            <xsl:apply-templates select="@*, node()"/>
        </xsl:copy>
        
        <!-- 判断第一个后续兄弟是否符合条件 -->
        <xsl:if test="following-sibling::*[1][self::p[starts-with(normalize-space(), 'Alternate')]]">
            <section>
                <!-- 用wrap模式处理后续兄弟,避免和默认模板冲突 -->
                <xsl:apply-templates select="following-sibling::*" mode="wrap"/>
            </section>
        </xsl:if>
    </xsl:template>
    
    <!-- 默认情况下,不输出Endofclause的后续兄弟 -->
    <xsl:template match="p[@outputclass='Endofclause']/following-sibling::*"/>
    
    <!-- 在wrap模式下,正常输出这些元素 -->
    <xsl:template match="*" mode="wrap">
        <xsl:copy>
            <xsl:apply-templates select="@*, node()" mode="wrap"/>
        </xsl:copy>
    </xsl:template>
    
</xsl:stylesheet>

方案2:用分组简化逻辑(XSLT 3.0专属)

利用xsl:for-each-group把<p outputclass="Endofclause">和前面的元素归为一组,直接处理分组后的内容,同时跳过后续兄弟的默认输出:

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    
    <xsl:mode on-no-match="shallow-copy"/>
    
    <!-- 对conbody的子元素分组,以Endofclause的p为分组结尾 -->
    <xsl:template match="conbody">
        <xsl:copy>
            <xsl:for-each-group select="*" group-ending-with="p[@outputclass='Endofclause']">
                <!-- 输出当前组的所有内容 -->
                <xsl:apply-templates select="current-group()"/>
                
                <!-- 检查是否需要包裹后续兄弟 -->
                <xsl:if test="current-group()[last()][following-sibling::*[1][self::p[starts-with(normalize-space(), 'Alternate')]]]">
                    <section>
                        <xsl:apply-templates select="current-group()[last()]/following-sibling::*"/>
                    </section>
                </xsl:if>
            </xsl:for-each-group>
        </xsl:copy>
    </xsl:template>
    
    <!-- 阻止后续兄弟被默认模板重复输出 -->
    <xsl:template match="p[@outputclass='Endofclause']/following-sibling::*"/>
    
</xsl:stylesheet>
最终效果

修改后的XSL处理你提供的输入XML,会得到没有重复内容的正确输出:

<?xml version="1.0" encoding="UTF-8"?><dita>
    <concept>
        <title>
            <ph>Page 5</ph> TEST XML</title>
        <conbody>
            <p>As prescribed in <ph>
                    <xref href="test2.dita#1234">2 TEST</xref>(a)</ph>, insert the following
                clause:</p>
            <p class="- topic/p " id="d3235e15" outputclass="Ctr_SmCaps">Shipment and Payment</p>
            
            <p class="- topic/p " outputclass="Endofclause">(End of clause)</p><section><p class="- topic/p " id="d3238e514">
                    <i class="+ topic/ph hi-d/i ">Alternate I</i> </p><p class="- topic/p ">
                    A2</p><p class="- topic/p ">
                A3</p></section>
 
        </conbody>
    </concept>
</dita>

内容的提问来源于stack exchange,提问作者Jino John Devasia

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 17:02:50