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

如何用XSLT为toc.ncx添加playOrder?批量重排navpoint序号问询

用XSLT自动为toc.ncx生成/重排playOrder的解决方案

刚好我之前处理过类似的NCX文件问题,用XSLT就能完美解决自动生成和重排playOrder的需求,不用再手动修改编号。下面是具体的实现方法:

核心XSLT代码

创建一个名为update-playorder.xsl的文件,内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:ncx="http://www.daisy.org/z3986/2005/ncx/"
    exclude-result-prefixes="ncx">

    <!-- 身份模板:复制所有原有节点和属性,保留原文件结构 -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <!-- 专门处理navpoint元素,自动生成连续的playOrder -->
    <xsl:template match="ncx:navpoint">
        <xsl:copy>
            <!-- 生成playOrder:按深度优先顺序为所有navpoint连续编号 -->
            <xsl:attribute name="playOrder">
                <xsl:number count="ncx:navpoint" level="any"/>
            </xsl:attribute>
            <!-- 保留原navpoint的其他属性(排除旧的playOrder避免冲突) -->
            <xsl:apply-templates select="@*[not(local-name()='playOrder')]"/>
            <!-- 处理子节点,确保嵌套的navpoint也能被编号 -->
            <xsl:apply-templates select="node()"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

代码说明

  • 命名空间处理:因为你的toc.ncx使用了DAISY NCX的默认命名空间,所以XSLT里用ncx前缀来匹配对应的元素,避免命名空间冲突。
  • 身份模板:保证原文件里的所有内容(比如<head>里的meta信息、<navlabel>、<content>等)都原封不动保留,只修改navpoint的playOrder属性。
  • 自动编号逻辑:<xsl:number count="ncx:navpoint" level="any"/>会遍历所有navpoint元素(包括嵌套的子节点),按照深度优先的顺序生成连续的整数,完全符合NCX规范里的线性阅读顺序要求。

使用方法

你可以用任意XSLT处理器来运行这个转换,比如:

  1. 命令行工具(Saxon):
    下载Saxon的JAR包后,执行命令:
    java -jar saxon9he.jar -s:toc.ncx -xsl:update-playorder.xsl -o:updated-toc.ncx
    
    其中toc.ncx是你的原文件,updated-toc.ncx是生成的带正确playOrder的新文件。
  2. XML编辑器:很多XML编辑器(比如Oxygen XML、XMLSpy)都自带XSLT转换功能,直接导入原文件和XSLT文件,执行转换即可。

解决新增navpoint后的重排问题

以后不管你在navmap的任何位置新增、删除或移动navpoint元素,只要重新运行一次这个XSLT转换,所有playOrder都会自动重新生成连续的编号,完全不用手动逐个修改,彻底解决大量元素时的繁琐操作。

举个简单例子,原文件里的嵌套navpoint会被自动编号成这样:

<navmap>
    <navpoint playOrder="1" id="navpoint-1">
        <navlabel><text>第一章</text></navlabel>
        <content src="chapter1.html"/>
        <navpoint playOrder="2" id="navpoint-1-1">
            <navlabel><text>1.1 小节</text></navlabel>
            <content src="chapter1-1.html"/>
        </navpoint>
    </navpoint>
    <navpoint playOrder="3" id="navpoint-2">
        <navlabel><text>第二章</text></navlabel>
        <content src="chapter2.html"/>
    </navpoint>
</navmap>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:45:26