如何让XSLT脚本从ditamap钻取两层文件并将数据汇总为单个HTML文件
问题原因说明
- 路径解析错误:原脚本直接嵌套调用
document()函数时,默认使用初始输入的根bookmap所在路径作为基准URI解析子文件路径,无法正确匹配嵌套ditamap的相对路径,导致子文件加载失败 - 节点匹配范围混乱:原脚本未明确限定节点匹配的文档范围,可能匹配到上层ditamap里的非目标节点,导致输出不符合预期
- 输出结构错误:原脚本循环生成多个
<html>根节点,不符合标准HTML文档规范
修复后的XSLT脚本
<?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:math="http://exslt.org/math" xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:s9ml="http://www.standardnine.com/s9ml" exclude-result-prefixes="xs math xd xhtml s9ml" xmlns="http://www.w3.org/1999/xhtml" version="3.0"> <xsl:template match="/"> <html> <body> <xsl:variable name="root-base-uri" select="static-base-uri()"/> <!-- 加载第一层子ditamap --> <xsl:for-each select="//mapref[@format='ditamap']"> <xsl:variable name="level1-href" select="resolve-uri(@href, $root-base-uri)"/> <xsl:variable name="level1-map" select="doc($level1-href)"/> <!-- 加载第二层目标ditamap --> <xsl:for-each select="$level1-map//mapref[@format='ditamap']"> <xsl:variable name="level2-href" select="resolve-uri(@href, $level1-href)"/> <xsl:variable name="level2-map" select="doc($level2-href)"/> <h2><xsl:value-of select="$level2-map/map/title"/></h2> <table border="1"> <xsl:apply-templates select="$level2-map//topicref"/> </table> </xsl:for-each> </xsl:for-each> </body> </html> </xsl:template> <xsl:template match="topicref"> <tr> <td><xsl:value-of select="tokenize(@href, '/')[last()]"/></td> <td><xsl:value-of select="topicsubject/@keyref"/></td> </tr> </xsl:template> </xsl:stylesheet>
关键改动说明
- 使用
static-base-uri()获取初始输入文件的基准路径,结合resolve-uri()函数拼接子文件的完整路径,确保嵌套层级的相对路径都能被正确解析 - 分层加载ditamap,明确指定每一层的加载来源和节点匹配范围,避免无关节点干扰
- 统一输出单个HTML文档结构,修复多根节点的语法问题
内容的提问来源于stack exchange,提问作者pantherfan
相关产品推荐
相关产品推荐

