我正在尝试使用 schematron 验证我的实例文档,并且在 Java XSLT 处理器实现方面遇到了问题。当我尝试从我的 schematron 生成一个 XSL 时,即使是一个简单的,我得到的结果与我期望的不同。
当使用 xsltproc (cygwin) 进行转换时,一切正常。但是使用 Saxon-B 9.1.0.8,默认的 java 1.6 实现或带有 Saxon-PE 9.3.0.5 的 Oxygen IDE 的 XSLT 调试器会生成一个无效的 XSL 文件。原因是包含前缀的元素的extension-element-prefixes
属性,没有在任何地方声明名称空间。这样的样式表在使用时必然会失败。xsl:stylesheet
exsl
手动编辑生成的文件是不可能的,因为 schematron 是在运行时在应用程序中生成的。我一定是做错了什么,对吧?我已经将问题追踪到了iso_schematron_skeleton_for_saxon.xsl
(或者iso_schematron_skeleton_for_xslt1.xsl
,取决于所使用的实现,是的,我都尝试了相同的最终结果)。尽管骨架清楚地创建了一个带有缺失名称空间的正确样式表,但它后来以某种方式神奇地被移除了。我不是真正的 XSLT 专家,所以我不知道我在这里做错了什么。我敢肯定这只是我在某个地方错过的一些愚蠢的事情。我想知道为什么下面输入的输出不同。
这是一个示例 schematron,它只定义了一些命名空间(我希望这被认为是一个有效的模式):
<?xml version="1.0" encoding="utf-8"?>
<sch:schema xmlns:sch="http://purl.oclc.org/dsdl/schematron"
queryBinding="exslt">
<sch:ns uri="http://exslt.org/dynamic" prefix="dyn"/>
<sch:ns xmlns:rng="http://relaxng.org/ns/structure/1.0"
xmlns:nma="urn:ietf:params:xml:ns:netmod:dsdl-annotations:1"
uri="urn:ietf:params:xml:ns:yang:ietf-inet-types"
prefix="inet"/>
<sch:ns xmlns:rng="http://relaxng.org/ns/structure/1.0"
xmlns:nma="urn:ietf:params:xml:ns:netmod:dsdl-annotations:1"
uri="urn:ietf:params:xml:ns:yang:ietf-ipfix-psamp"
prefix="ipfix"/>
<sch:ns xmlns:rng="http://relaxng.org/ns/structure/1.0"
xmlns:nma="urn:ietf:params:xml:ns:netmod:dsdl-annotations:1"
uri="urn:ietf:params:xml:ns:yang:ietf-yang-types"
prefix="yang"/>
<sch:ns xmlns:rng="http://relaxng.org/ns/structure/1.0"
xmlns:nma="urn:ietf:params:xml:ns:netmod:dsdl-annotations:1"
uri="urn:ietf:params:xml:ns:netconf:base:1.0"
prefix="nc"/>
</sch:schema>
这是我从 Java XSLT 处理器获得的片段(这个来自 Oxygen,无论使用 xslt1 还是 xslt2 的 iso,问题仍然存在):
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--This XSLT was automatically generated from a Schematron schema.-->
<xsl:stylesheet xmlns:sch="http://www.ascc.net/xml/schematron"
xmlns:set="http://exslt.org/sets"
xmlns:str="http://exslt.org/strings"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:date="http://exslt.org/dates-and-times"
xmlns:dyn="http://exslt.org/dynamic"
xmlns:iso="http://purl.oclc.org/dsdl/schematron"
xmlns:math="http://exslt.org/math"
xmlns:random="http://exslt.org/random"
xmlns:regexp="http://exslt.org/regular-expressions"
xmlns:inet="urn:ietf:params:xml:ns:yang:ietf-inet-types"
xmlns:ipfix="urn:ietf:params:xml:ns:yang:ietf-ipfix-psamp"
xmlns:yang="urn:ietf:params:xml:ns:yang:ietf-yang-types"
xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"
extension-element-prefixes="date dyn exsl math random regexp set str"
version="1.0">
<!--Removed in favor of brevity.-->
</xsl:stylesheet>
以下是 xsltproc 生成的内容,以及我希望 java 生成的内容:
<?xml version="1.0" standalone="yes"?>
<!--This XSLT was automatically generated from a Schematron schema.-->
<axsl:stylesheet
xmlns:date="http://exslt.org/dates-and-times"
xmlns:dyn="http://exslt.org/dynamic"
xmlns:exsl="http://exslt.org/common"
xmlns:math="http://exslt.org/math"
xmlns:random="http://exslt.org/random"
xmlns:regexp="http://exslt.org/regular-expressions"
xmlns:set="http://exslt.org/sets"
xmlns:str="http://exslt.org/strings"
xmlns:axsl="http://www.w3.org/1999/XSL/Transform"
xmlns:sch="http://www.ascc.net/xml/schematron"
xmlns:iso="http://purl.oclc.org/dsdl/schematron"
xmlns:inet="urn:ietf:params:xml:ns:yang:ietf-inet-types"
xmlns:ipfix="urn:ietf:params:xml:ns:yang:ietf-ipfix-psamp"
xmlns:yang="urn:ietf:params:xml:ns:yang:ietf-yang-types"
xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"
extension-element-prefixes="date dyn exsl math random regexp set str"
version="1.0">
<!--Removed in favor of brevity.-->
</axsl:stylesheet>
如您所见,Java 输出缺少对应前缀的 exsl 命名空间。我意识到应该处理命名空间的iso骨架部分被标记为实验性的。如果有必要,我愿意应用肮脏的黑客来让它工作(除非我因为没有深入学习schematron而问一些尴尬的事情)。有任何想法吗?
编辑:正如 Martin 在下面的评论中建议的那样,我尝试使用纯 XSLT 1.0 处理器。我使用了 xalan(编译版和解释版)和 saxon 6.5.5。两个 xalans 都没有附加 exsl 命名空间。Saxon 甚至无法处理带有“添加属性后无法添加名称空间”或类似内容的 schematron(xslt1 的 iso 框架中的第 1534 行)。对我来说,唯一能够使用 queryBinding="exslt" 转换 schematron 的处理器仍然是 xsltproc。它也是我尝试过的唯一非 Java 处理器。在阅读了一些有问题的 XSL 之后,我注意到一条评论,其中声称该转换已使用 saxon9 进行了测试。所以这应该有效。
PS:为长篇文章道歉,但我认为举个例子很重要。