Adam Mackler | 20 Jun 2012 04:36
Gravatar

Schematron to validate XML representations

Hi:

In the Restlet book (page 108), it says regarding validation of XML documents that, "we recommend you use
XML Schema...or modern alternatives such as Relax NG or Schematron."  I'm interested in using Schematron.

I'm using Restlet 2.0.14.  In the XMLRepresentation class, the getSchemaLanguageUri() method that
returns the value passed to javax.xml.validation.SchemaFactory.newInstance() in getSchema()
(which is called by setSchema(Representations) shown in the book) only seems to be able to return values
for W3C Schema and RELAXNG.

Even if I use the setSchema() that takes a compiled schema as an argument, I still need to pass an argument to
SchemaFactory.newInstance() that will work with Schematron.  javax.xml.XMLConstants has String
constants for W3C Schema and RELAX NG, but not Schematron.

I am wanting to validate XML representations using both Schematron in conjunction with W3C Schema by
putting the Schematron rules inside <appinfo> tags in the xsd schema.  How can I do this?  The Restlet book
does not give an example.  A search of this mailing list for "schematron" produces no results.  If there is an
example somewhere that I am not finding, or if someone could show me how to accomplish this I would be most grateful.

Thank you very much,
Adam Mackler

------------------------------------------------------
http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447&dsMessageId=2972130

Adam Mackler | 25 Jun 2012 09:44
Gravatar

RE: Schematron to validate XML representations

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>

(Continue reading)

Adam Mackler | 29 Jun 2012 11:32
Gravatar

RE: Schematron to validate XML representations

I need to update my previous post as I have noticed a bug.  The code that I posted does not distinguish between
validation errors in the W3C schema and errors in the XML request entity submitted by the user.  Obviously
the first problem should return an HTTP response with a 5XX error status and the latter a 4XX error status.

I have have changed the file named Base.java that I posted above.  I replaced the try/catch block that
contained the line "requestEntity.validate(xsd);" with the following:

	final StreamSource schemaSource = new StreamSource(xsd.getStream());
	schemaSource.setSystemId("schema");
	final InputSource entitySource = new InputSource(requestEntity.getStream());
	entitySource.setSystemId("entity");

	try {
	    SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI).newSchema(schemaSource)
		.newValidator().validate(new SAXSource(entitySource));
	} catch (Exception e) {
	    if (e instanceof org.xml.sax.SAXParseException) {
		SAXParseException spe = (SAXParseException)e;
		StringBuffer message = new StringBuffer("Invalid XML at ");
		message.append("line " + spe.getLineNumber() + " column of "+ spe.getColumnNumber());
		if (spe.getSystemId().matches(".*schema")) {
		    message.append(" schema");
		    throw new ResourceException(Status.SERVER_ERROR_INTERNAL, message.toString(), e);
		} else {
		    message.append(" HTTP request entity");
		    throw new ResourceException(Status.CLIENT_ERROR_UNPROCESSABLE_ENTITY,
						message.toString(), e);
		}
	    } else {
		throw new ResourceException(Status.SERVER_ERROR_INTERNAL, "XML validation FAIL", e);
(Continue reading)


Gmane