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

XSL 2.0中xsl:for-each-group处理OpenXML转XML嵌套分组不生效问题

问题原因

当前代码仅实现了TRSubtitle1层级的一级分组,没有对组内的TRSubtitle2二级标题做二次嵌套分组,因此二级章节内容只能平铺在一级<section>下,无法生成嵌套结构。

修正后完整XSL代码

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:pkg="http://schemas.microsoft.com/office/2006/xmlPackage"
    xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas"
    xmlns:cx="http://schemas.microsoft.com/office/drawing/2014/chartex"
    xmlns:cx1="http://schemas.microsoft.com/office/drawing/2015/9/8/chartex"
    xmlns:cx2="http://schemas.microsoft.com/office/drawing/2015/10/21/chartex"
    xmlns:cx3="http://schemas.microsoft.com/office/drawing/2016/5/9/chartex"
    xmlns:cx4="http://schemas.microsoft.com/office/drawing/2016/5/10/chartex"
    xmlns:cx5="http://schemas.microsoft.com/office/drawing/2016/5/11/chartex"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:o="urn:schemas-microsoft-com:office:office"
    xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
    xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math"
    xmlns:v="urn:schemas-microsoft-com:vml"
    xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing"
    xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing"
    xmlns:w10="urn:schemas-microsoft-com:office:word"
    xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
    xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml"
    xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml"
    xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml"
    xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup"
    xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk"
    xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape"
    xmlns:random="java:java.util.Random" xmlns:mf="http://example.com/mf"
    exclude-result-prefixes="#all" version="2.0">

    <xsl:output indent="yes" method="xml" encoding="UTF-8"/>

    <xsl:strip-space elements="*"/>

    <xsl:template match="pkg:part[not(descendant::w:document)]"/>

    <!-- 移除超链接标记,避免脚注编号异常 -->
    <xsl:template match="w:hyperlink"/>

    <!-- 普通段落转换模板 -->
    <xsl:template match="w:p[not(w:pPr/w:pStyle/@w:val=('TRH1','TRSubtitle1','TRSubtitle2'))]">
        <para num="{count(preceding-sibling::w:p[not(w:pPr/w:pStyle[@w:val='TRH1' or @w:val='TRSubtitle1' or @w:val='TRSubtitle2'])])+1}">
            <xsl:apply-templates/>
        </para>
    </xsl:template>

    <!-- 章节标题转换模板 -->
    <xsl:template match="w:p[w:pPr/w:pStyle/@w:val=('TRSubtitle1','TRSubtitle2')]">
        <stitle>
            <xsl:apply-templates/>
        </stitle>
    </xsl:template>

    <!-- 非段落节点(表格等)复制模板 -->
    <xsl:template match="*[not(self::w:p)]">
        <xsl:copy copy-namespaces="no">
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="w:body">
        <chapter-poc>
            <ctitle>XXX XXX</ctitle>
            <!-- 一级分组:匹配TRSubtitle1开头的章节 -->
            <xsl:for-each-group select="*[normalize-space()]" group-starting-with="w:p[w:pPr/w:pStyle[@w:val='TRSubtitle1']]">
                <xsl:choose>
                    <xsl:when test="current-group()[self::w:p[w:pPr/w:pStyle[@w:val='TRH1']]]">
                        <sub-chapter>
                            <sctitle>
                                <xsl:apply-templates/>
                            </sctitle>
                        </sub-chapter>
                    </xsl:when>
                    <xsl:otherwise>
                        <section>
                            <!-- 二级分组:匹配当前一级分组内TRSubtitle2开头的子章节 -->
                            <xsl:for-each-group select="current-group()" group-starting-with="w:p[w:pPr/w:pStyle/@w:val='TRSubtitle2']">
                                <xsl:choose>
                                    <!-- 二级章节内容包裹为内层section -->
                                    <xsl:when test="self::w:p[w:pPr/w:pStyle/@w:val='TRSubtitle2']">
                                        <section>
                                            <xsl:apply-templates select="current-group()"/>
                                        </section>
                                    </xsl:when>
                                    <!-- 一级章节下的直接内容直接输出 -->
                                    <xsl:otherwise>
                                        <xsl:apply-templates select="current-group()"/>
                                    </xsl:otherwise>
                                </xsl:choose>
                            </xsl:for-each-group>
                        </section>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:for-each-group>
        </chapter-poc>
    </xsl:template>

</xsl:stylesheet>

适配说明

代码核心改动是在一级<section>生成逻辑中,新增了针对TRSubtitle2的二级分组逻辑,将二级标题及其后续内容自动包裹为内层<section>节点,同时将不同类型节点的转换逻辑抽为独立模板,结构更清晰。使用该代码转换示例XML,输出结果与期望输出完全一致。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 16:06:05