I am attempting to validate my instance documents with schematron and having trouble with Java XSLT processor implementations. When I try to generate an XSL from my schematron, even a simple one, I get different results from what I expect to get.
When xsltproc (cygwin) is used to do the transformation everything's okay. But using Saxon-B 9.1.0.8, the default java 1.6 implementation or Oxygen IDE's XSLT debugger with Saxon-PE 9.3.0.5 generates a non-valid XSL file. The cause being the extension-element-prefixes
attribute of the xsl:stylesheet
element containing the exsl
prefix, for which a namespace is not declared anywhere. Such a stylesheet is bound to fail when used.
Manually editing the generated files is out of the question since schematron is generated in an application at runtime. I've got to be doing something wrong, right? I've tracked the problem into the iso_schematron_skeleton_for_saxon.xsl
(or iso_schematron_skeleton_for_xslt1.xsl
, depending on the implementation used, yes I tried both with the same end result). Even though the skeleton clearly creates a proper stylesheet with the missing namespace, it is later somehow magically removed. I'm am not really an XSLT expert, so I have no idea what I'm doing wrong here. I'm sure it's just some silly thing I missed somewhere. I'd like to know why the output for the input below differs.
Here's a sample schematron which does nothing but defines some namespaces (I hope this is considered a valid schema):
<?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>
Here's the snippet I get from Java XSLT processors (this one is from Oxygen, doesn't matter if iso for xslt1 or xslt2 is used, the problem persists):
<?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>
Here's what xsltproc generates and what I wish java would too:
<?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>
As you can see the Java output is missing an exsl namespace for the corresponding prefix. I realize that the part of iso skeleton which is supposed to process the namespaces is flagged as experimental..I'm willing to apply dirty hacks to get this to work if neccessary (unless I'm asking something embarrassing due not learning schematron in depth). Any ideas?
Edit: as Martin suggested in a comment below I tried using a pure XSLT 1.0 processor. I used xalan (both compiled and interpretive versions) and saxon 6.5.5. Neither of the xalans appends the exsl namespace. Saxon even fails to process the schematron with "cannot add a namespace after attributes have been added" or something similar (line 1534 in the iso skeleton for xslt1). The only processor able to transform a schematron with queryBinding="exslt" for me remains xsltproc. It is also the only non-java processor I tried. After reading a bit of the offending XSL I noticed a comment in which a claim is made that the transformation has been tested with saxon9. So this SHOULD work.
P.S.: apologies for the long post but I think it's vital to give an example of this.
queryBinding="xslt2"
in your schema instead ofqueryBinding="exslt"
you have. After all once you use an XSLT/XPath 2.0 implementation of Schematron you shouldn't have any need to use EXSLT extensions. – Martin Honnen