DocBook5转HTML时xsl:value-of无法获取title值问题排查
问题成因
你遇到的取值为空问题,是三个规则理解偏差叠加导致的:
- XPath命名空间匹配规则认知错误:XSLT中XPath表达式内不带前缀的元素名,不会使用
xmlns=声明的结果树默认命名空间,而是由xpath-default-namespace属性指定匹配的命名空间;未配置该属性时,无前缀元素名默认匹配无命名空间节点。你的源DocBook所有元素都属于http://docbook.org/ns/docbook命名空间,因此title、./title、/title这类无前缀写法,根本无法匹配到源文件中的节点。 - 前缀与路径使用错误:测试用的
xs:title、xsl:title、h:title分别对应XML Schema、XSLT、XHTML命名空间,和DocBook命名空间完全无关,不可能匹配到目标节点;/db:title是绝对路径写法,仅匹配文档根节点下的直接子title,而DocBook根节点为book,顶层title存放在book/info路径下,自然返回空值。 - 不了解DocBook XSLT NG的预处理逻辑:DocBook NG不会直接处理原始源树,会先将源文档转换为规范化的临时树:把所有直接挂载在part/chapter/section等元素下、未放在info块内的标题、元数据,统一移动到对应元素的info子节点下。你在
m:docbook模式下拿到的db:part是临时树中的规范化节点,直接子节点已经不存在title元素,因此db:title、./db:title这类取直接子节点的写法也会返回空。
解决方法
按以下两步调整即可正常取值:
- 在
xsl:stylesheet根节点上添加xpath-default-namespace="http://docbook.org/ns/docbook"属性,配置后XPath中不带前缀的元素名默认匹配DocBook命名空间,无需每次都加db:前缀。 - 调整title取值路径,适配规范化后的节点结构,优先取info下的title,同时兼容原始结构,写法为
select="(info/title, db:info/db:title, title, db:title)[1]",可以覆盖所有场景取到第一个有效标题值。
修改后的可用自定义模板示例:
<?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:db="http://docbook.org/ns/docbook" xmlns:m="http://docbook.org/ns/docbook/modes" xmlns:h="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/xhtml" xpath-default-namespace="http://docbook.org/ns/docbook" exclude-result-prefixes="xsl xs db m h" version="3.0"> <xsl:import href="https://cdn.docbook.org/release/xsltng/current/xslt/docbook.xsl" /> <xsl:template match="db:part" mode="m:docbook"> <xsl:variable name="partTitle" select="(info/title, db:info/db:title, title, db:title)[1]" /> <section class="part"> <h1 class="title"> <xsl:value-of select="$partTitle"/> </h1> <xsl:next-match/> </section> </xsl:template> </xsl:stylesheet>
补充说明:如果不需要兼容原始非规范DocBook结构,DocBook NG完成预处理后,part的title一定会存放在info子节点下,直接使用
select="info/title"即可取值。
内容的提问来源于stack exchange,提问作者SMt
相关产品推荐
相关产品推荐

