XSLT 中的预处理
是否可以在 XSLT 中进行“预处理”?
通过预处理,我的意思是更新源树的(在内存中的表示形式)。
这是可能的,还是我需要为其进行多次转换。
用例: 我们为我们的客户提供了 Docbook 参考手册,但对于某些客户来说,它们需要不同的“皮肤”(不同的图像等)。所以我希望做的是根据参数转换图像 fileref 路径。然后应用其余的常规 Docbook XSL 模板。
is it at all possible to 'pre-proccess' in XSLT?
with preprocessing i mean updating the (in memory representation) of the source tree.
is this possible, or do i need to do multiple transforms for it.
use case:
we have Docbook reference manuals for out clients but for certain clients these need different 'skins' (different images etc). so what i was hoping to do is transform the image fileref path depending on a parameter. then apply the rest of the normal Docbook XSL templates.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
扩展 Eamon 的答案...
对于 XSLT 1.0 或 2.0,您首先将中间(预处理)结果放入中。元素,全局(顶级)或本地(模板内)声明。
在 XSLT 2.0 中,$intermediate-result 变量的值是由一个文档节点(在 XSLT/XPath 1.0 中称为“根节点”)组成的节点序列。您可以像访问任何其他变量一样访问和使用它,例如 select="$intermediate-result/doc"
但在 XSLT 1.0 中,$intermediate-result 变量的值不是一流的节点集。相反,它是所谓的“结果树片段”。它的行为类似于包含一个根节点的节点集,但您使用它的方式受到限制。您可以复制它并获取其字符串值,但无法使用 XPath 向下钻取,如 select="$intermediate-result/doc" 中所示。为此,您必须首先使用处理器的 node-set() 扩展函数将其转换为一流的节点集。在 Saxon 6.5、libxslt 和 4xslt 中,您可以使用 exsl:node-set() (如 Eamon 的答案)。在 MSXML 中,您需要使用 msxsl:node-set(),其中 xmlns:msxsl="urn:schemas-microsoft-com:xslt",在 Xalan 中,我相信它被称为 xalan:nodeset() (没有连字符,但您必须通过 Google 查找名称空间 URI)。例如: select="exsl:node-set($intermediate-result)/doc"
XSLT 2.0 简单地废除了结果树片段,使得 node-set() 变得不必要。
Expanding on Eamon's answer...
In the case of either XSLT 1.0 or 2.0, you'd start by putting the intermediate (pre-processed) result in an <xsl:variable> element, declared either globally (top-level) or locally (inside a template).
In XSLT 2.0, the value of the $intermediate-result variable is a node sequence consisting of one document node (was called "root node" in XSLT/XPath 1.0). You can access and use it just as you would any other variable, e.g., select="$intermediate-result/doc"
But in XSLT 1.0, the value of the $intermediate-result variable is not a first-class node-set. Instead, it's something called a "result tree fragment". It behaves like a node-set containing one root node, but you're restricted in how you can use it. You can copy it and get its string-value, but you can't drill down using XPath, as in select="$intermediate-result/doc". To do that, you must first convert it to a first-class node-set using your processor's node-set() extension function. In Saxon 6.5, libxslt, and 4xslt, you can use exsl:node-set() (as in Eamon's answer). In MSXML, you'd need to use msxsl:node-set(), where xmlns:msxsl="urn:schemas-microsoft-com:xslt", and in Xalan, I believe it's called xalan:nodeset() (without the hyphen, but you'll have to Google for the namespace URI). For example: select="exsl:node-set($intermediate-result)/doc"
XSLT 2.0 simply abolished the result tree fragment, making node-set() unnecessary.
这对于符合标准的 XSLT 1.0 来说是不可能的。然而,在我使用过的每个实际实现中都是可能的。然而,执行此操作的扩展因引擎而异。在标准 XSLT 2.0 中也是可能的(无论如何,它更容易使用 - 所以如果可以的话,就使用它)。
如果您的 xslt 处理器支持 EXSLT,则 exsl:node-set() 函数可以满足您的需求。 msxml 也有一个相同名称的扩展函数(但使用不同的命名空间 uri,不幸的是,这些函数并不完全兼容)。
This is not possible with standards compliant XSLT 1.0. It is possible in every actual implementation I've used, however. The extensions with which to do that differ by engine, however. It is also possible in standard XSLT 2.0 (which is in any case much easier to work with - so if you can, just use that).
If your xslt processor supports EXSLT, the exsl:node-set() function does what you're looking for. msxml has an identically named extension function as well (but with a different namespace uri, the functions are unfortunately not trivially compatible).
由于您尝试从同一 DocBook XML 源生成略有不同的输出,因此您可能需要研究 DocBook XSL 样式表中的“分析”(条件标记)支持。请参阅 第 26 章 /docbookxsl/" rel="nofollow noreferrer">DocBook XSL:完整指南作者:Bob Stayton:
例如,要对同一文档的 Windows 和 Mac 版本使用不同的图像,您可能有一个如下所示的 DocBook XML 片段:
然后,您将使用 DocBook XSL 样式表的支持分析的版本以及
profile.os
参数设置为windows
或mac
。Since you are trying to generate slightly different output from the same DocBook XML source, you might want to look into the "profiling" (conditional markup) support in DocBook XSL stylesheets. See Chapter 26 in DocBook XSL: The Complete Guide by Bob Stayton:
For example, to use different images for, say, Windows and Mac versions of the same document, you might have a DocBook XML fragment like this:
Then, you would use the profiling-enabled versions of the DocBook XSL stylesheets with the
profile.os
parameter set towindows
ormac
.也许您应该在这里使用 XSLT“OOP”方法。将所有客户端的所有通用模板放入样式表中,并为每个客户端创建一个样式表,其中特定模板覆盖通用模板。使用 xsl:import 将公共样式表导入到特定样式表中,您只需调用与客户端对应的样式表即可进行一次处理。
Maybe you should use XSLT "OOP" methods here. Put all the common templates to all clients in a stylesheet, and create an stylesheet for each client with specific templates overriding common ones. Import the common stylesheet within the specific ones with xsl:import, and you'll do only one processing by calling the stylesheet corresponding to a client.