xmlperlschematrondocbook-5

Using Schematron with Perl


I am trying to follow along with this article on Schematron and Perl.

http://www.xml.com/pub/a/2002/01/23/perl-schematron.html?page=2

My goal is to use Schematron, along with RelaxNG, to validate Docbook 5 documents.

However, I can't seem to get this basic example to work. Here's my Perl script, copied from the O'Reilly article:

#!/usr/bin/perl -w
use strict;
use XML::Schematron::LibXSLT;


my $schema_file = $ARGV[0];
my $xml_file    = $ARGV[1];

die "Usage: perl schematron.pl schemafile XMLfile.\n"
    unless defined $schema_file and defined $xml_file;

my $tron = XML::Schematron::LibXSLT->new();

$tron->schema($schema_file);
my $ret = $tron->verify($xml_file);

print $ret . "\n";

I call the script like this:

perl schematron.pl path-to-docbook.sch path-to-xml-file

I get back errors having to do with the namespace "db":

xsltCompileStepPattern : no namespace bound to prefix db
compilation error: file unknown-101d82900 element template
xsltCompilePattern : failed to compile 'db:sidebar'
error
...

My docbook.sch file begins as follows. It is the docbook.sch schema file that comes with the Docbook 5 distribution:

<?xml version="1.0" encoding="utf-8"?>
<s:schema xmlns:s="http://www.ascc.net/xml/schematron" xmlns:db="http://docbook.org/ns/docbook">
  <s:ns prefix="db" uri="http://docbook.org/ns/docbook"/>
  <s:pattern name="Element exclusion">
    <s:rule context="db:sidebar">

Could it be that the Perl module uses a version of Schematron that doesn't understand namespaces? Or could it be that docbook.sch is incorrect? That would be strange, since it comes with the Docbook distribution.

I may be missing something fundamental, because I'm new to Schematron.


Solution

  • This looks like a bug in XML::Schematron. The following line in docbook.sch is not taken into account:

    <s:ns prefix="db" uri="http://docbook.org/ns/docbook"/> 
    

    The validation is done by turning the schema into an XSLT stylesheet. I was able to make the error go away by adding the DocBook namespace declaration in the XSLTProcessor.pm module:

    $self->append_template(
           qq|<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
           <xsl:stylesheet $ns version="1.0"
                xmlns:db="http://docbook.org/ns/docbook">   
           <xsl:output method="text"/>
           <xsl:template match="/">
           <xsl:apply-templates select="/" mode="$mode"/>|
       );
    

    The above is just a hack. A proper fix (which I haven't attempted) should of course work for any namespace declared in a Schematron schema.