For anyone interested, here is the solution I've come up with. Again, I am validating the XML documents in HTTP request entities against a W3C Schema that also contains embedded Schematron rules. Notes:
*) In addition to the files referenced in the code, the Schematron skeleton file is also necessary (available in the same place as the other schematron files). *) I had to install SAXON, which, FYI, uses XSLT2 *) I am new to this. No doubt there are better ways to do this. I welcome and invite all feedback. First some example content and then the working code below. The following XML entity when PUT to my server should validate: <person> <firstName>Charles</firstName> <lastName>Smith</lastName> <gender>male</gender> </person> The following XML entity when PUT to my server should NOT validate because (1) the person is missing a first name and (2) because it is a male with a maiden name. These rules will be enforced by Schematron. <person> <lastName>Smith</lastName> <maidenName>Dudley</maidenName> <gender>male</gender> </person> The following XML entity when put to my server should NOT validate because the document element is not a person. This will be enforced by a W33 Schema. <invalid /> This is the schema file called schema/tron.xsd in my classpath. It is a W3C Schema with Schematron annotations: <?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" xmlns:sch="http://purl.oclc.org/dsdl/schematron"> <xs:element name="person"> <xs:annotation> <xs:appinfo> <sch:pattern name="No men with maiden names"> <sch:rule context="person[gender='male']"> <sch:report test="maidenName">A person element with a gender element equal to male must not contain a maidenName sub-element</sch:report> </sch:rule> </sch:pattern> </xs:appinfo> </xs:annotation> <xs:complexType> <xs:sequence> <xs:element name="firstName" type="xs:token" minOccurs="0"> <xs:annotation> <xs:appinfo> <sch:pattern name="All persons must have first names"> <sch:rule context="person"> <sch:assert test="firstName">All person elements must have a firstName element as a child.</sch:assert> </sch:rule> </sch:pattern> </xs:appinfo> </xs:annotation> </xs:element><!-- end of firstname --> <xs:element name="lastName" type="xs:token"/> <xs:element name="maidenName" type="xs:token" minOccurs="0"/> <xs:element name="gender"> <xs:simpleType> <xs:restriction base="xs:token"> <xs:enumeration value="male"/> <xs:enumeration value="female"/> </xs:restriction> </xs:simpleType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:schema> This is my ServerResource subclass in a file called org/mackler/resource/InstanceResource.java: package org.mackler.resource; imports... public class InstanceResource extends org.mackler.resource.Base { @Put("xml") public StringRepresentation put(DomRepresentation requestEntity) throws IOException, SAXException, ResourceException, ParserConfigurationException { validate(requestEntity, "tron"); return new StringRepresentation("\nyou validated this: \n" + requestEntity.getText()+"\n"); } } End of org/mackler/resource/InstanceResource.java: This is the base class that all my ServerResources that need to validate can inherit from. It's in a file called org/mackler/resource/Base.java: package org.mackler.resource; imports... public class Base extends ServerResource { public void validate(DomRepresentation requestEntity, String schemaName) throws IOException, ResourceException, SAXException, ParserConfigurationException { ClientResource xsdResource = new ClientResource(LocalReference.createClapReference("/schema/" + schemaName +".xsd")); Representation xsd; /* Beginning of W3C Schema validation code */ try { xsd = xsdResource.get(); } catch (ResourceException e) { throw new ResourceException(Status.SERVER_ERROR_INTERNAL, "Error getting the W3C XML Schema: " + xsdResource.getReference().toString(), e ); } try { requestEntity.validate(xsd); } catch (Exception e) { throw new ResourceException(Status.CLIENT_ERROR_UNPROCESSABLE_ENTITY, "Request entity failed validate against W3C Schema", e); } /* End of W3C Schema validation code */ /* Beginning of Schematron validation code */ try { xsd = xsdResource.get(); } catch (ResourceException e) { throw new ResourceException(Status.SERVER_ERROR_INTERNAL, "Error getting the Schematron-annotated XML Schema: " + xsdResource.getReference().toString(), e ); } /* Schematron files are from here: * http://code.google.com/p/schematron/source/browse/trunk/schematron/code/ */ ClientResource extractorResource = new ClientResource(LocalReference.createClapReference("/schema/ExtractSchFromXSD-2.xsl")); ClientResource svrlResource = new ClientResource(LocalReference.createClapReference("/schema/iso_svrl_for_xslt2.xsl")); Representation extractor; Representation svrl; try { extractor = extractorResource.get(); } catch (ResourceException e) { throw new ResourceException(Status.SERVER_ERROR_INTERNAL, "Error getting the transformation stylesheet needed to extract Schematron rules: " + extractorResource.getReference().toString(), e ); } try { svrl = svrlResource.get(); } catch (ResourceException e) { throw new ResourceException(Status.SERVER_ERROR_INTERNAL, "Error getting the Schematron implementation: " + " " + svrlResource.getReference().toString(), e ); } /* So far we have: * xsd: the user's W3C schema (containing the embedded schematron rules) * extractor: xslt sheet to extracts schematron annotations from the W3C schema; * svrl: xslt implementation of the schematron validatior report language; * For details on how these parts work together, see the * section labelled "Under the Hood" on * http://www.schematron.com/ */ // Extract the Schematron schema from the W3C Schema annotations: TransformRepresentation schematronRules = new TransformRepresentation(xsd, extractor); /* Apply svrl to schematronSchema * The context enables creation of the URI resolver that works * with CLAP, needed for SVRL to find the included the skeleton * Schematron implementation translation sheet in the * classpath */ TransformRepresentation schematronSchema = new TransformRepresentation(getContext(), schematronRules, svrl); /* Validate the HTTP XML request entity */ TransformRepresentation report = new TransformRepresentation(requestEntity, schematronSchema); // Do some DOM manipulation to find any errors in the Schematron report DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); DocumentBuilder documentBuilder = factory.newDocumentBuilder(); Document document = documentBuilder.parse(report.getStream()); NodeList nodeList = document.getElementsByTagNameNS("http://purl.oclc.org/dsdl/svrl", "text"); if ( nodeList.getLength() > 0 ) { StringBuilder message = new StringBuilder(); int i = 0; while (i < nodeList.getLength()) { message.append(( i==0 ? "" : "; ") + ((Text)nodeList.item(i++).getFirstChild()).getData()); } throw new ResourceException(Status.CLIENT_ERROR_UNPROCESSABLE_ENTITY, "Schematron validation failure: " + message.toString()); } xsd.release(); extractor.release(); svrl.release(); schematronRules.release(); schematronSchema.release(); /* End of Schematron validation code */ } } ------------------------------------------------------ http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447&dsMessageId=2973037