对Docbook元素树分支进行XSL转换

2 投票
1 回答
782 浏览
提问于 2025-04-16 02:00

我想用docbook的XSL样式表来渲染文档的不同部分,而不是把整个文档都转换。

问题是,有些部分包含了<footnoteref>元素,而这些元素的linkend属性并不在同一块内容里。换句话说,我想处理一部分树状结构,这部分包括<footnoteref>,但不包括它们所引用的<footnote>元素。

我尝试用Python的lxml库来实现这个功能,但遇到了这个错误信息:

XSLTApplyError                            Traceback (most recent call last)

/var/www/mpd/<ipython console> in <module>()

/var/www/mpd/<ipython console> in <genexpr>((elt,))

/usr/lib/python2.6/dist-packages/lxml/etree.so in lxml.etree.XSLT.__call__ (src/lxml/lxml.etree.c:109204)()

XSLTApplyError: Internal error in xsltKeyFunction(): Could not get the document info of a context doc.

这个错误是在执行,比如说etree.XSLT(etree.parse('docbook.xsl'))(some_element)时出现的。

我使用的是普通的xhtml样式表。我不认为使用哪个样式表会有什么影响。

有没有什么支持的方法来做到这一点?或者我是不是应该先对文档应用XSLT转换,把<footnoteref>元素转换成<footnote>元素,然后再进行渲染?但这样做又不行,因为那样会出现多个相同ID的<footnote>标签。这个转换只能在<footnote>标签不被包含在结果树中时进行。我本来以为这已经是默认的行为了。不过希望我只是漏掉了某个设置。

编辑

感谢@Jukka的回答,我发现我可以传递rootid参数给XSLT处理器,只渲染那个ID的内容。然而,这样做的效果太忠实了,输出的内容只是引用了脚注,和如果整个文档作为一个HTML页面渲染时的片段是一样的。比如说:

>>> xsl_url_html = 'http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl'
>>> from lxml import etree
>>> consume_result = etree.XSLT(etree.parse(xsl_url_xhtml))(
        etree.parse(my_xml_file), rootid=etree.XSLT.strparam("command_consume"))
>>> etree.tostring(consume_result).split('\n')
['<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',
 '<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=ASCII" /><title></title><meta name="generator" content="DocBook XSL Stylesheets V1.75.2" /></head><body><dt><a id="command_consume"></a><span class="term">',
 '            <div class="cmdsynopsis"><p><code class="command">consume</code>  {<em class="replaceable"><code>STATE</code></em>}</p></div>',
 '          </span></dt><dd><p>',
 '              <sup>[<a href="#ftn.since_0_15" class="footnoteref">2</a>]</sup>',
 '              Sets consume state to <code class="varname">STATE</code>,',
 '              <code class="varname">STATE</code> should be 0 or 1.',
 '\t      When consume is activated, each song played is removed from playlist.',
 '            </p></dd></body></html>']

也许还有其他参数可以让脚注在同一页面上显示,最好是从1开始编号?我想这个参数可能在这个列表中的某个地方。我会找时间去看看。

1 个回答

0

与其试图把DocBook XSL样式表应用到单个元素上,不如把它应用到整个文档上,但可以用rootid参数来指定你想要转换的文档部分。

根据参考文档的说明:

整个文档会被加载和解析,但格式化会从你指定的元素开始,而不是从文档的根部开始。例如,这样可以只处理一本书的第4章。

因为整个文档都可以被处理器访问,所以自动编号、交叉引用和其他依赖关系都能正确解决。

撰写回答