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

XSLT转换Open XML为整洁HTML列表:嵌套列表转换失败求助

解决Word Open XML嵌套列表转HTML的XSLT问题

嘿,你遇到的嵌套列表转换问题在处理Word Open XML时挺常见的——主要是因为Word的列表结构依赖w:numPr里的ilvl(层级)和numId(列表标识),而XSLT需要主动跟踪这些值来正确生成嵌套的<ul>/<ol>结构。

先拆解你给出的XML片段里的关键信息:

  • <w:pStyle w:val="ListParagraph"/> 标记这是一个列表段落
  • <w:ilvl w:val="0"/> 表示这是第0级(顶级)列表项
  • <w:numId w:val="1"/> 表示属于ID为1的列表

之前你的XSLT可能没有处理层级切换的逻辑,导致嵌套列表无法正确闭合或开启。下面是一个针对性的解决方案:

核心思路

  1. 跟踪当前的列表ID(current-numId)和层级(current-ilvl),每次遇到新的列表段落时对比这两个值
  2. 当层级加深时,嵌套新的<ul>/<ol>;层级变浅时,关闭对应数量的列表标签
  3. 同一列表ID下的不同层级要保持列表类型一致(比如项目符号对应<ul>,编号对应<ol>)

完整XSLT示例代码

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
  <!-- 全局变量跟踪当前列表状态 -->
  <xsl:variable name="current-numId" select="''"/>
  <xsl:variable name="current-ilvl" select="-1"/>

  <!-- 匹配文档根节点 -->
  <xsl:template match="/">
    <html>
      <body>
        <xsl:apply-templates select="w:document/w:body/*"/>
      </body>
    </html>
  </xsl:template>

  <!-- 处理普通段落 -->
  <xsl:template match="w:p[not(w:pPr/w:numPr)]">
    <p>
      <xsl:apply-templates select="w:t"/>
    </p>
  </xsl:template>

  <!-- 处理列表段落 -->
  <xsl:template match="w:p[w:pPr/w:numPr]">
    <xsl:variable name="numId" select="w:pPr/w:numPr/w:numId/@w:val"/>
    <xsl:variable name="ilvl" select="number(w:pPr/w:numPr/w:ilvl/@w:val)"/>
    <!-- 实际场景可通过w:numbering节点判断是项目符号还是编号列表 -->
    <xsl:variable name="is-bullet" select="true()"/>

    <!-- 切换列表ID时,关闭之前的所有列表 -->
    <xsl:if test="$numId != $current-numId">
      <xsl:call-template name="close-lists">
        <xsl:with-param name="level" select="$current-ilvl"/>
      </xsl:call-template>
      <xsl:variable name="current-numId" select="$numId"/>
    </xsl:if>

    <!-- 处理层级加深的情况 -->
    <xsl:if test="$ilvl > $current-ilvl">
      <xsl:call-template name="open-lists">
        <xsl:with-param name="start-level" select="$current-ilvl + 1"/>
        <xsl:with-param name="end-level" select="$ilvl"/>
        <xsl:with-param name="is-bullet" select="$is-bullet"/>
      </xsl:call-template>
    </xsl:if>

    <!-- 处理层级变浅的情况 -->
    <xsl:if test="$ilvl < $current-ilvl">
      <xsl:call-template name="close-lists">
        <xsl:with-param name="level" select="$current-ilvl"/>
        <xsl:with-param name="target-level" select="$ilvl"/>
      </xsl:call-template>
    </xsl:if>

    <!-- 输出列表项内容 -->
    <li>
      <xsl:apply-templates select="w:t"/>
    </li>

    <!-- 更新当前层级变量 -->
    <xsl:variable name="current-ilvl" select="$ilvl"/>
  </xsl:template>

  <!-- 辅助模板:递归打开多层嵌套列表 -->
  <xsl:template name="open-lists">
    <xsl:param name="start-level"/>
    <xsl:param name="end-level"/>
    <xsl:param name="is-bullet"/>
    <xsl:if test="$start-level <= $end-level">
      <xsl:choose>
        <xsl:when test="$is-bullet"><ul></xsl:when>
        <xsl:otherwise><ol></xsl:otherwise>
      </xsl:choose>
      <xsl:call-template name="open-lists">
        <xsl:with-param name="start-level" select="$start-level + 1"/>
        <xsl:with-param name="end-level" select="$end-level"/>
        <xsl:with-param name="is-bullet" select="$is-bullet"/>
      </xsl:call-template>
    </xsl:if>
  </xsl:template>

  <!-- 辅助模板:递归关闭多层嵌套列表 -->
  <xsl:template name="close-lists">
    <xsl:param name="level"/>
    <xsl:param name="target-level" select="-1"/>
    <xsl:if test="$level > $target-level">
      </ul>
      <xsl:call-template name="close-lists">
        <xsl:with-param name="level" select="$level - 1"/>
        <xsl:with-param name="target-level" select="$target-level"/>
      </xsl:call-template>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>

关键细节说明

  • 状态跟踪:通过全局变量记录当前的列表ID和层级,确保每次处理列表段落时能精准对比层级变化
  • 递归处理嵌套:用open-lists和close-lists两个递归模板处理多层嵌套的开启与关闭,避免冗余代码
  • 列表类型适配:示例里用is-bullet简化处理,实际可以读取Word文档中<w:numbering>节点的定义,自动判断生成<ul>还是<ol>

测试你的片段

针对你给出的顶级列表项(ilvl="0"),这段XSLT会输出:

<ul>
  <li>[你的段落文本]</li>
</ul>

如果后续有ilvl="1"的嵌套项,会自动生成:

<ul>
  <li>[顶级文本]
    <ul>
      <li>[嵌套文本]</li>
    </ul>
  </li>
</ul>

记得补充列表类型判断的逻辑(读取w:numbering节点),这样处理不同类型的列表会更准确!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 04:21:46