预处理 XSL 样式表 - 包括外部文档

Posted

技术标签:

【中文标题】预处理 XSL 样式表 - 包括外部文档【英文标题】:Preprocess XSL Stylesheet - include external documents 【发布时间】:2021-01-31 10:34:26 【问题描述】:

我需要对多个 XML 文件进行转换。为了进行转换,我有一个包含各种 xsl 样式表的文件夹。我需要使用 Java 解析器进行转换,并且我不控制任何样式表的内容。

样式表通过xsl:import 语句相互引用,它们还包含如下css样式:

<style type="text/css">
    <xsl:value-of select="document('../../common/display.css')" disable-output-escaping="yes"/>
</style>

简化示例

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:import href="../../common/functions.xsl"/>

    <xsl:template match="/">
        <html>
            <head>
                <title>..</title>
                <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
                <style type="text/css">
                    <xsl:value-of select="document('../../common/display.css')" disable-output-escaping="yes"/>
                </style>
            </head>
            <body>
                <xsl:apply-templates/>
            </body>
        </html>
    </xsl:template>
</xsl:stylesheet>

通过使用以下样式表进行首次处理,我设法包含了所有其他 xsl 文件。

<?xml version="1.0" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                version="1.0">

<xsl:template match="xsl:include">
  <xsl:copy-of select="document(@href)/xsl:stylesheet/*"/>
</xsl:template>

<xsl:template match="@*|node()">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>

</xsl:stylesheet>

但是我不知道如何对 css 引用做同样的事情。是否甚至可以评估 xsl:value-of 以获取对 document() 的调用中的字符串的值,或者获取外部 css 文件的内容?

【问题讨论】:

【参考方案1】:

根据 XSLT 规范,处理 xsl:include 的方式不正确,原因有很多:复制的指令将具有与原始指令不同的范围内命名空间,它们将具有不同的控制值versionexclude-result-prefixes等属性

以这种方式处理xsl:import 更具挑战性,因为需要尊重导入优先级。基本上,您可以在多模块样式表中完成一些在单模块样式表中无法完成的事情。

对于document() 上的调用,要准确找到调用,您需要解析所有 XPath 表达式。如果document() 的参数是字符串文字,那么在大多数情况下,应该可以生成一个包含所引用文档内容的全局变量,并将document() 上的调用替换为对该变量的引用。 (但请注意基本 URI)。

您实际上并没有说出通过这种方式转换样式表想要实现的目标。费了很大的力气,看不出有什么成果。

【讨论】:

感谢您的回答迈克尔。首先,我想要实现的是以下内容。我有许多 java 项目,它们都编译成 azure 函数。基本上每个项目都是特定类型的 xml 消息的解析器。解析器函数执行 xml -> json、json -> xml 和 xml -> html。为了包含 xsl 样式表作为我的 java 函数的资源,我需要为我的 xslt 转换器(我正在使用 Saxon HE)提供自定义路径解析器,或者指向一个不包含外部文件的 xsl 样式表。问题的根源在于导入中的相对路径。 我实际上已经通过添加自定义路径解析器解决了这个问题,但我很想知道我是否也可以通过嵌入 css 文件内容来做到这一点。哦,我知道您提出的有关处理 xsl:include 和导入的问题。目前我实际上正在用 xsl:include 替换所有出现的 xsl:import 理想情况下,我希望有预编译的 Saxon Templates 对象并在我的转换中使用它,但我不知道如何实现。 标准的TransformerFactory.newTemplates(source) 方法将按照所有xsl:includexsl:import 引用构造单个编译样式表。如果 URI 是静态已知的,Saxon 还具有一个配置选项,用于预加载使用 doc()document() 函数引用的文档。【参考方案2】:

如果您想通过 XSLT 样式表访问 CSS 文件,请使用 unparsed-text() 函数而不是 document() 函数。

https://www.cw3.org/TR/2017/REC-xpath-functions-31-20170321/#func-unparsed-text

doument() 函数假定目标为 XML 文件并返回文档节点。 unparsed-text() 函数将目标视为文本文件并将整个内容返回为xs:string

但是您不能使用 XSLT 1.0 版,而是应该使用支持 XSLT 3.0 的处理器,例如 Saxon HE。

【讨论】:

以上是关于预处理 XSL 样式表 - 包括外部文档的主要内容,如果未能解决你的问题,请参考以下文章

XSLT

xml 错误 xsl 样式表

XSL 转换以输出许多嵌入式 XSL 样式表

如何使用 XSL 生成 HTML 文件?

对同一个 XSL 样式表使用不同的 HTML 模板

为啥 XSL 样式表显示没有 XML(信息/值)的 html 表