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

如何用XSLT将带style的p标签转为li并生成HTML5合规结构?

解决XSLT分组转换blockquote内p标签的问题

需求说明

  • 将<blockquote>内带@style属性的<p>标签转换为<li>元素
  • 不带@style属性的<p>标签保持原有结构
  • 连续的带@style的<p>需被包裹在独立的<ul>中,不带@style的<p>作为外层<div>的直接子元素,避免出现<p>作为<ul>子元素的不规范结构

输入内容

<blockquote>
<p style="margin-left: 40px;">test</p>
<p style="margin-left: 40px;">some test</p>
<p style="margin-left: 40px;">another test</p>
<p>
    <em>paragraph</em>
</p>
<p style="margin-left: 40px;">a</p>
<p style="margin-left: 40px;">b</p>
<p style="margin-left: 40px;">c</p>
<p>
    <em>another paragraph</em>
</p>
<p style="margin-left: 40px;">qwert</p>
<p style="margin-left: 40px;">asdf</p>
<p style="margin-left: 40px;">sdfg</p>
<p>
    <em>another para</em>
</p>
<p style="margin-left: 40px;">sdfg</p>
<p style="margin-left: 40px;">asdf</p>
<p style="margin-left: 40px;">qwert</p>
</blockquote>

现有XSLT模板

<xsl:template match="blockquote">
    <xsl:element name="div">
        <xsl:attribute name="class" select="'section-content'"/>
        <xsl:attribute name="data-class" select="'blockquote'"/>
        <xsl:attribute name="data-unlock" select="'ALL'"/>
        <xsl:element name="ul">
            <xsl:apply-templates/>
        </xsl:element>
    </xsl:element>
</xsl:template>

<xsl:template match="blockquote/p[@style]">
    <xsl:element name="li">
        <xsl:apply-templates/>
    </xsl:element>
</xsl:template>

<xsl:template match="blockquote/p[not(@style)]">
    <xsl:element name="p">
        <xsl:apply-templates/>
    </xsl:element>
</xsl:template>

当前输出问题

现有模板会将所有内容包裹在一个<ul>中,导致不带@style的<p>成为<ul>的子元素,违反HTML5规范,输出结构如下:

<div class="section-content" data-class="blockquote" data-unlock="ALL">
<ul>
    <li>test</li>
    <li>some test</li>
    <li>another test</li>                     
    <p>
        <i>paragraph</i>
    </p>
    <li>a</li>
    <li>b</li>
    <li>c</li>
    <p>
        <i>another paragraph</i>
    </p>
    <li>qwert</li>
    <li>asdf</li>
    <li>sdfg</li>
    <p>
        <i>another para</i>
    </p>
    <li>sdfg</li>
    <li>asdf</li>
    <li>qwert</li>
</ul>
</div>

期望输出

连续的带@style的<p>被包裹在独立<ul>中,不带@style的<p>作为外层<div>的直接子元素:

<div class="section-content" data-class="blockquote" data-unlock="ALL">
<ul>
    <li>test</li>
    <li>some test</li>
    <li>another test</li>
</ul>                         
<p>
    <i>paragraph</i>
</p>
<ul>
    <li>a</li>
    <li>b</li>
    <li>c</li>
</ul>   

<p>
    <i>another paragraph</i>
</p>
<ul>
    <li>qwert</li>
    <li>asdf</li>
    <li>sdfg</li>
</ul>
<p>
    <i>another para</i>
</p>
<ul>
    <li>sdfg</li>
    <li>asdf</li>
    <li>qwert</li>
</ul>
</div>

解决方案

需要使用XSLT的分组功能(xsl:for-each-group)对连续的带@style的<p>进行分组,替换原有的<blockquote>模板,同时保留原有针对<p>的模板:

<xsl:template match="blockquote">
    <div class="section-content" data-class="blockquote" data-unlock="ALL">
        <!-- 按相邻节点分组:区分带style的p和不带style的p -->
        <xsl:for-each-group select="*" group-adjacent="boolean(self::p[@style])">
            <xsl:choose>
                <!-- 如果是连续的带style的p,包裹到ul中 -->
                <xsl:when test="current-grouping-key()">
                    <ul>
                        <xsl:apply-templates select="current-group()"/>
                    </ul>
                </xsl:when>
                <!-- 不带style的p直接输出 -->
                <xsl:otherwise>
                    <xsl:apply-templates select="current-group()"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each-group>
    </div>
</xsl:template>

<!-- 保留原有带style的p转li的模板 -->
<xsl:template match="blockquote/p[@style]">
    <li>
        <xsl:apply-templates/>
    </li>
</xsl:template>

<!-- 保留原有不带style的p的模板 -->
<xsl:template match="blockquote/p[not(@style)]">
    <p>
        <xsl:apply-templates/>
    </p>
</xsl:template>

思路说明

  1. 使用xsl:for-each-group的group-adjacent属性,按节点是否为带@style的<p>进行相邻分组
  2. 对于分组结果,带@style的连续节点组被包裹在<ul>中,每个<p>转为<li>
  3. 不带@style的节点组直接输出,作为外层<div>的直接子元素,避免了不规范的嵌套结构

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 10:14:53