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

如何修改XSL将含h标签的扁平XML转换为层级XML

适配XSL将扁平h/p结构转换为层级section结构

我懂你的痛点——之前的XSL是为带class的标题p标签写的,现在你把标题换成了h标签,层级用h的class(head1/head2/head3)区分,原代码肯定没法直接用了。咱们来调整代码,完美适配你的新结构:

修改后的完整XSL代码

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                xmlns:xs="http://www.w3.org/2001/XMLSchema" 
                xmlns:mf="http://example.com/mf" 
                exclude-result-prefixes="xs mf" 
                version="2.0">
    <xsl:output indent="yes"/>

    <!-- 身份模板:复制所有未被匹配的节点 -->
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>

    <!-- 递归分组函数:处理指定层级的标题及下属内容/子标题 -->
    <xsl:function name="mf:group" as="element(section)*">
        <xsl:param name="entries" as="element()*"/>
        <xsl:param name="level" as="xs:integer"/>

        <xsl:for-each-group select="$entries" 
                            group-starting-with="h[@class = concat('head',$level)]">
            <!-- 只有当分组起始节点是当前层级的标题时才创建section -->
            <xsl:if test="self::h[@class = concat('head',$level)]">
                <xsl:variable name="current-heading-id" select="generate-id(.)"/>
                <section name="{@class}">
                    <title>
                        <xsl:value-of select="."/>
                    </title>

                    <!-- 收集当前标题之后、下一个标题之前的所有p内容 -->
                    <xsl:variable name="content-paragraphs" 
                                 select="following-sibling::p[generate-id(preceding-sibling::h[@class][1]) = $current-heading-id]"/>
                    <xsl:if test="$content-paragraphs">
                        <ps>
                            <xsl:apply-templates select="$content-paragraphs"/>
                        </ps>
                    </xsl:if>

                    <!-- 递归处理当前分组中除了当前标题的其他节点,处理下一层级标题 -->
                    <xsl:sequence select="mf:group(current-group() except ., $level + 1)"/>
                </section>
            </xsl:if>
        </xsl:for-each-group>
    </xsl:function>

    <!-- 匹配body节点,启动分组逻辑 -->
    <xsl:template match="body">
        <xsl:copy>
            <!-- 传入所有h(标题)和p(内容)节点,从level 1开始分组 -->
            <xsl:sequence select="mf:group(*[self::h or self::p], 1)"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

关键修改点说明

  • 函数参数类型更新:把mf:group的第一个参数从element(p)*改成element()*,这样能同时处理h标题和p内容节点。
  • 分组起始节点调整:将原代码中匹配p[@class]的地方全部换成h[@class],因为现在标题是h标签了。
  • body模板调用优化:传入*[self::h or self::p],确保所有标题和内容节点都被纳入分组处理,而不是只筛选带head的节点。
  • 内容段落选择修正:调整了p内容节点的匹配逻辑,确保只选中当前标题到下一个标题之间的段落,避免跨层级错误。
  • 增加分组有效性判断:加了<xsl:if test="self::h[@class = concat('head',$level)]",防止非目标节点触发无效的section创建。

验证效果

用你提供的输入XML运行修改后的XSL,就能生成你想要的嵌套section结构:

<body>
   <section name="head1">
      <title>1: Heading level 1</title>
      <ps>
         <p>some text here</p>
         <p>some text here</p>
      </ps>
      <section name="head2">
         <title>1.1: Heading level 2</title>
         <ps>
            <p>some text here</p>
            <p>some text here</p>
         </ps>
         <section name="head3">
            <title>1.1.1: Heading level 3</title>
            <ps>
               <p>some text here</p>
               <p>some text here</p>
            </ps>
         </section>
      </section>
   </section>
   <section name="head1">
      <title>2: Heading level 1</title>
      <section name="head2">
         <title>2.1: Heading level 2</title>
         <ps>
            <p>some text here</p>
            <p>some text here</p>
         </ps>
         <section name="head3">
            <title>2.1.1: Heading level 3</title>
            <ps>
               <p>some text here</p>
               <p>some text here</p>
            </ps>
         </section>
         <section name="head3">
            <title>2.1.2: Heading level 3</title>
            <ps>
               <p>some text here</p>
               <p>some text here</p>
            </ps>
         </section>
      </section>
   </section>
</body>

内容的提问来源于stack exchange,提问作者Stéphane Garcia

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 17:07:52