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

如何将block元素分组到<p class="p">内?求替代XSLT实现方案

问题:合并特定XML节点的XSLT替代写法

需求说明

将<block>元素以及后续的<p class="p1">内容合并到前置的<p class="p">元素内部,触发条件为:<p class="p">的第一个后续兄弟节点是<block>元素。

输入XML文件

<root>
    <p class="p">aaaaaa</p>
    <block>
        <p>block</p>
    </block>
    <p class="p1"> bbb </p>
    <block>
        <p>block</p>
    </block>
    <p class="p1">bbb.</p>
    <p class="p">cccc</p>
</root>

期望输出XML文件

<root>
    <p class="p">aaaaaa<block><p>block</p></block> bbb <block><p>block</p></block>bbb.</p>
    <p class="p">cccc</p>
</root>

当前使用的XSLT代码

<xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    
    
    <xsl:template match="p[@class='p']">
        <xsl:choose>
            <xsl:when test="following-sibling::*[1][self::block]">
                <xsl:text disable-output-escaping="yes">&lt;p&gt;</xsl:text>
                <xsl:apply-templates/>
            </xsl:when>
            <xsl:otherwise>
                <p><xsl:apply-templates select="@*|node()"/></p>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
    
    <xsl:template match="p[@class='p1']">
        <xsl:choose>
            <xsl:when test="following-sibling::*[1][self::p[@class='p']]">
                <xsl:apply-templates/>
                <xsl:text disable-output-escaping="yes">&lt;/p&gt;</xsl:text>
            </xsl:when>
            <xsl:otherwise>
                <xsl:apply-templates/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

更规范的替代写法

你当前的写法依赖disable-output-escaping手动拼接XML标签,这种方式不够健壮,容易导致输出XML格式错误。推荐使用XSLT标准的节点处理逻辑实现,以下是替代方案:

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

<!-- 匹配需要合并的p[@class='p']节点 -->
<xsl:template match="p[@class='p'][following-sibling::*[1][self::block]]">
    <p class="p">
        <!-- 处理当前p节点的内容 -->
        <xsl:apply-templates select="node()"/>
        <!-- 处理后续所有非p[@class='p']的兄弟节点,用merge模式 -->
        <xsl:apply-templates select="following-sibling::*[not(self::p[@class='p'])]" mode="merge"/>
    </p>
</xsl:template>

<!-- merge模式:直接复制block和p1节点 -->
<xsl:template match="block|p[@class='p1']" mode="merge">
    <xsl:copy-of select="."/>
</xsl:template>

<!-- 阻止被合并的原block和p1节点输出 -->
<xsl:template match="block[preceding-sibling::*[1][self::p[@class='p']]]|p[@class='p1'][preceding-sibling::block]"/>

逻辑说明

  1. 匹配符合触发条件的<p class="p">节点,复制该节点并在其内部先处理自身内容。
  2. 通过merge模式,将后续所有<block>和<p class="p1">节点直接复制到当前<p class="p">内部。
  3. 最后编写模板,让原本要被合并的<block>和<p class="p1">节点不再单独输出,避免重复。

这种写法完全基于XSLT的节点处理机制,输出的XML结构更可靠,也更易于维护。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 18:10:05