Re: James Clark releases new implementation of Schematron as part of Jing

James Clark <[email protected]> Fri, 20 Jun 2003 20:34:44 +0700
Newsgroups gmane.text.xml.schematron
Message-ID <[email protected]>
Rick Jelliffe wrote:

> He seems to have some trick to allow instant death
> when the first error is found; I expect this is a user option.

Hmm.  It's not supposed to do that.  If the Schematron fails RELAX NG 
validation, then it won't try to compile it.  But if the schema's OK, it 
should report all errors in the instance as normal.  If you have a case 
where it doesn't, please send me a bug report.  I wouldn't be surprised 
if there were bugs.

> He has made his own
> XSLT meta-stylesheet as well: he validates the Schematron schema using a RELAX NG 
> (consise syntax) schema, which means he can take most of the validation out of the 
> stylesheet.

The meta-stylesheet has a couple of interesting features.  One is the 
error reporting.  Jing expects validators to report errors (both in the 
schema and the instance) via a SAX ErrorHandler, and I think it's highly 
desirable that these errors include line-numbers.  The tactic I've 
adopted for getting line-numbers out of XSLT processors is to use 
extension functions. This works with Saxon and Xalan (at least with the 
current version). It could easily be made to work with XT. It can work 
with libxml/libxslt (with an extension function in Python). We can 
distinguish several different kinds of error:

- Simple, structural errors in the schema.  These are dealt with by 
RELAX NG validation.

- More complex cross-reference errors in the schema (e.g. IDREFs 
pointing to the wrong kind of thing).  We handle these by having the 
meta stylesheet detect these errors. For each error it detects, it 
generates an extension element in the XSLT. The output of applying the 
meta-stylesheet to the Schematron schema is run through a SAX 
ContentHandler that detects these extension elements and outputs a 
message through the ErrorHandler.

- Errors in XPaths in the schema.  Each start-tag in the output XSLT 
that contains an XPath that came from the Schematron schema is annotated 
with extension attributes giving the original line-number.  The second 
stylesheet is compiled directly from the SAX events generated by the 
first stylesheet. The trick is that to insert a filter in between the 
output and the stylesheet compiler that reads the extension attributes 
and reports locations to the stylesheet compiler based on these 
extension attributes rather than the actual line-numbers in the 
generated stylesheet.  The net result is that XPath errors are reported 
in terms of the original Schematron input.

- Errors in the instance.  The second transformation generates an XML 
document which contains an element for each message and these elements 
are annotated with line-column number.  The second transformation feeds 
into a SAX content handler that outputs a message through the ErrorHandler.

The meta-stylesheet also uses a different strategy from the reference 
implementation for compiling patterns and rules into a set of XSLT 
templates.  The goal is improved efficiency.  I haven't done enough 
testing to know whether it actually succeeds.  It probably won't be 
noticeable in a client environment, where the running time seems to be 
dominated by Java overhead (startup and JIT time).  There are two ideas 
underlying the strategy.  One is to minimize the number of traversals of 
the XSLT tree.  The other is to minimize the number of times you match a 
set of templates against a node.  In the generated XSLT, there is a mode 
for each pattern and also a mode that combines all rules. There are two 
templates generated for each rule, one in its pattern's mode and one in 
the combined mode.  The combined mode imposes an arbitrary order on the 
patterns and generates priorities to ensure no conflict.  The combined 
mode is used to find the first rule that matches; the template in the 
combined mode then falls back to the per-pattern modes to ensure that 
the errors from all patterns are reported.  This should be much more 
efficient with schemas that are "sparse" (i.e. there are many instance 
elements for which there are matching rules in few or no patterns): an 
instance element that doesn't match any rules can be handled using a 
single XSLT matching operation (as opposed to one matching operation for 
each pattern).

There's one really hairy part on the Java side, which stems from the 
fact that JAXP XSLT interface wants to be in control of things (i.e. it 
only provides a transform() method that accepts a SAX XMLReader for the 
input and a SAX ContentHandler for the output).  In the context of NRL, 
NRL needs to be in control: it needs to get a ContentHandler into which 
it can feed SAX events.  This would also be the case in any context 
where you wanted to use Schematron to validate the output of a process 
rather than the input.  I deal with this by using a separate thread to 
run the XSLT transformation as a coroutine.

James










-------------------------------------------------------
This SF.Net email is sponsored by: INetU
Attention Web Developers & Consultants: Become An INetU Hosting Partner.
Refer Dedicated Servers. We Manage Them. You Get 10% Monthly Commission!
INetU Dedicated Managed Hosting http://www.inetu.net/partner/index.php