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

嵌套for-each实现多级标题章节列表的XSL转换问题求助

解决多级标题XSL转换的方案

嘿,我懂你遇到的麻烦了——硬写嵌套的<xsl:for-each>确实搞不定任意层级的标题,毕竟你没法提前知道文档到底有多少级 heading。给你个用递归模板的解决方案,能完美处理这种动态层级的情况:

首先先补全你给出的XML示例(方便测试和演示):

<Chapters>
  <Chapter>
    <Heading1Lvl>
      <Heading1LvlName>heading1nameFirst</Heading1LvlName>
      <Heading2Lvl>
        <Heading2LvlName>heading2name</Heading2LvlName>
        <Text typeOfText="basic">BasicText</Text>
        <Heading3Lvl>
          <Heading3LvlName>heading3name</Heading3LvlName>
          <Text typeOfText="detailed">DetailedText</Text>
        </Heading3Lvl>
      </Heading2Lvl>
      <Heading2Lvl>
        <Heading2LvlName>anotherHeading2</Heading2LvlName>
      </Heading2Lvl>
    </Heading1Lvl>
    <Heading1Lvl>
      <Heading1LvlName>heading1nameSecond</Heading1LvlName>
    </Heading1Lvl>
  </Chapter>
</Chapters>

然后是对应的XSLT代码,核心用递归模板处理任意深度的标题:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" indent="yes"/>

  <!-- 入口模板,匹配根节点,初始化输出结构 -->
  <xsl:template match="/">
    <html>
      <body>
        <h1>章节列表</h1>
        <!-- 启动递归:找到所有第一层标题节点 -->
        <xsl:apply-templates select="Chapters/Chapter/*[starts-with(local-name(), 'Heading') and ends-with(local-name(), 'Lvl')]"/>
      </body>
    </html>
  </xsl:template>

  <!-- 递归核心模板:匹配所有标题层级节点 -->
  <xsl:template match="*[starts-with(local-name(), 'Heading') and ends-with(local-name(), 'Lvl')]">
    <!-- 从节点名里提取标题级别数字,比如从Heading2Lvl拿到2 -->
    <xsl:variable name="level" select="substring-before(substring-after(local-name(), 'Heading'), 'Lvl')"/>
    <!-- 生成对应级别的HTML标题标签 -->
    <xsl:element name="h{$level}">
      <xsl:value-of select="*[ends-with(local-name(), 'Name')]"/>
    </xsl:element>
    <!-- 输出当前标题下的文本内容 -->
    <xsl:apply-templates select="Text"/>
    <!-- 递归处理当前标题下的子标题,自动适配任意深度 -->
    <xsl:apply-templates select="*[starts-with(local-name(), 'Heading') and ends-with(local-name(), 'Lvl')]"/>
  </xsl:template>

  <!-- 专门处理Text节点的模板,格式化输出文本 -->
  <xsl:template match="Text">
    <p><xsl:value-of select="."/></p>
  </xsl:template>
</xsl:stylesheet>

关键逻辑说明:

  • 递归模板的优势:不像嵌套for-each只能处理固定层级,这个模板会自动查找当前标题节点下的所有子标题,递归调用自己,不管你的文档有3级还是10级标题都能处理。
  • 动态识别标题级别:通过字符串提取从节点名里拿到级别数字,不用硬写h1、h2,适配所有编号的标题节点。
  • 灵活的节点匹配:用starts-with和ends-with匹配标题节点,就算后续新增Heading4Lvl、Heading5Lvl也不用修改代码。

如果你的XML结构有细微调整(比如子标题的嵌套路径不同),只需要修改递归模板里的select路径就行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:01:39