1

这是我关于文档功能的问题。

文档函数是否总是为每个转换读取输入文件?还是第一次将其加载到内存中,然后从内存中读取以进行连续转换?

在这里问这个问题的原因是,我有一个非常输入文件,它总是在转换过程中检查值。

如何在这些情况下实现最佳性能?

4

3 回答 3

2

XSLT 2.0 中的函数规范document解析 XML 从单个 URL 的细节委托给XSLT/XPath/XQuerydoc函数的规范。它没有指定解析后的文档是否被缓存,但它要求函数是稳定的,说“默认情况下,这个函数是·stable·。如果相同的URI引用(在解析到两个调用都提供了一个绝对 URI 引用。因此,以下表达式(如果它没有引发错误)将始终为真:doc("foo.xml") is doc("foo.xml")"。

如果您想多次访问同一个文档,实现缓存结果可能是一个优势,但如果您加载多个大型文档并且无法处理任何一个,则可能是一个劣势。

您使用哪种 XSLT 2.0 处理器?Saxon 有http://www.saxonica.com/documentation/index.html#!functions/saxon/discard-document来显式丢弃缓存的文档,从而表明对document('foo.xml')或的调用doc('foo.xml')通常被缓存。

于 2013-08-21T12:34:35.840 回答
2

使用 doc() 或 document() 读取的文档几乎不可避免地会在转换期间被缓存,因为这是满足规范中稳定性要求的唯一方法。但我认为您的问题是关于跨多个转换的缓存。这将取决于处理器。

现在几乎没有理由使用 Saxon 6.5。即使出于可移植性原因您想将自己限制为 XSLT 1.0,通常最好使用较新的 Saxon 版本。

Saxon(至少是当前版本,我不记得是 6.5)将在 JAXP Transformer 的生命周期内缓存文档,因此如果您将同一个 Transformer 用于多个转换,则不会重新解析文档。如需更精确的控制,请考虑使用 s9api API。这允许您使用 DocumentBuilder 在内存中构建文档树,然后将其作为样式表参数的值传递给每个转换,或者通过注册一个识别 URIResolver 来响应对 doc() 或 document() 的调用URI。当然 - 使用任何 JAXP 转换引擎 - 您可以在 URIResolver 中实现自己的文档缓存。

于 2013-08-21T18:28:34.620 回答
1

当您使用该document()功能时,库无法知道您是否会再次使用它,或者这是否是临时访问。
每当您处理文档时,都必须对其进行解析等,这是相对耗时的。为了避免多次重新读取和重新解析文档的开销,库维护了一个“文档列表”作为“转换上下文”的一部分。任何被访问的文档的解析图像都被添加到这个列表中,并且列表(连同它引用的文档)只有在转换上下文被释放时才会被释放。

于 2013-08-21T12:15:16.637 回答