From: <bo...@us...> - 2008-03-07 04:56:37
|
Revision: 246 http://xmlunit.svn.sourceforge.net/xmlunit/?rev=246&view=rev Author: bodewig Date: 2008-03-06 20:56:39 -0800 (Thu, 06 Mar 2008) Log Message: ----------- Add instance validation and document new Validator class Modified Paths: -------------- trunk/xmlunit/src/java/org/custommonkey/xmlunit/jaxp13/Validator.java trunk/xmlunit/src/user-guide/XMLUnit-Java.xml trunk/xmlunit/tests/java/org/custommonkey/xmlunit/jaxp13/test_Validator.java Modified: trunk/xmlunit/src/java/org/custommonkey/xmlunit/jaxp13/Validator.java =================================================================== --- trunk/xmlunit/src/java/org/custommonkey/xmlunit/jaxp13/Validator.java 2008-03-06 08:49:51 UTC (rev 245) +++ trunk/xmlunit/src/java/org/custommonkey/xmlunit/jaxp13/Validator.java 2008-03-07 04:56:39 UTC (rev 246) @@ -42,6 +42,7 @@ import javax.xml.transform.Source; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; +import org.custommonkey.xmlunit.exceptions.XMLUnitRuntimeException; import org.xml.sax.ErrorHandler; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; @@ -56,13 +57,14 @@ */ public class Validator { private final String schemaLanguage; + private final SchemaFactory factory; private final ArrayList sources = new ArrayList(); /** * validates using W3C XML Schema 1.0. */ public Validator() { - this(XMLConstants.W3C_XML_SCHEMA_NS_URI); + this(XMLConstants.W3C_XML_SCHEMA_NS_URI, null); } /** @@ -72,7 +74,27 @@ * javax.xml.validation.SchemaFactory SchemaFactory}. */ public Validator(String schemaLanguage) { + this(schemaLanguage, null); + } + + /** + * validates using the specified schema factory. + */ + public Validator(SchemaFactory factory) { + this(null, factory); + } + + /** + * validates using the specified schema language or factory. + * + * @param schemaLanguage the schema language to use - see {@link + * javax.xml.validation.SchemaFactory SchemaFactory}. + * @param schemaFactory the concrete factory to use. If this is + * non-null, the first argument will be ignored. + */ + protected Validator(String schemaLanguage, SchemaFactory factory) { this.schemaLanguage = schemaLanguage; + this.factory = factory; } /** @@ -97,28 +119,90 @@ */ public List/*<SAXParseException>*/ getSchemaErrors() { final ArrayList l = new ArrayList(); - ErrorHandler h = new ErrorHandler() { - public void error(SAXParseException e) { - l.add(e); - } - public void fatalError(SAXParseException e) { - l.add(e); - } - public void warning(SAXParseException e) { - l.add(e); - } - }; try { - parseSchema(h); + parseSchema(new CollectingErrorHandler(l)); } catch (SAXException e) { // error has been recorded in our ErrorHandler anyway } return l; } + /** + * Is the given schema instance valid according to the configured + * schema definition(s)? + * + * @throws XMLUnitRuntimeException if the schema definition is + * invalid or the Source is a SAXSource and the underlying + * XMLReader throws an IOException (see {@link + * javax.xml.validation.Validator#validate validate in + * Validator}). + */ + public boolean isInstanceValid(Source instance) + throws XMLUnitRuntimeException { + return getInstanceErrors(instance).size() == 0; + } + + /** + * Obtain a list of all errors in the given instance. + * + * <p>The list contains {@link org.xml.sax.SAXParseException + * SAXParseException}s.</p> + * + * @throws XMLUnitRuntimeException if the schema definition is + * invalid or the Source is a SAXSource and the underlying + * XMLReader throws an IOException (see {@link + * javax.xml.validation.Validator#validate validate in + * Validator}). + */ + public List/*<SAXParseException>*/ getInstanceErrors(Source instance) + throws XMLUnitRuntimeException { + Schema schema = null; + try { + schema = parseSchema(null); + } catch (SAXException e) { + throw new XMLUnitRuntimeException("Schema is invalid", e); + } + + final ArrayList l = new ArrayList(); + javax.xml.validation.Validator v = schema.newValidator(); + v.setErrorHandler(new CollectingErrorHandler(l)); + try { + v.validate(instance); + } catch (SAXException e) { + // error has been recorded in our ErrorHandler anyway + } catch (java.io.IOException i) { + throw new XMLUnitRuntimeException("Error reading instance source", + i); + } + return l; + } + private Schema parseSchema(ErrorHandler h) throws SAXException { - SchemaFactory fac = SchemaFactory.newInstance(schemaLanguage); + SchemaFactory fac = factory != null ? factory + : SchemaFactory.newInstance(schemaLanguage); fac.setErrorHandler(h); - return fac.newSchema((Source[]) sources.toArray(new Source[0])); + try { + return fac.newSchema((Source[]) + sources.toArray(new Source[sources.size()])); + } finally { + fac.setErrorHandler(null); + } } + + private static final class CollectingErrorHandler implements ErrorHandler { + private final List l; + + CollectingErrorHandler(List l) { + this.l = l; + } + public void error(SAXParseException e) { + l.add(e); + } + public void fatalError(SAXParseException e) { + l.add(e); + } + public void warning(SAXParseException e) { + l.add(e); + } + } } \ No newline at end of file Modified: trunk/xmlunit/src/user-guide/XMLUnit-Java.xml =================================================================== --- trunk/xmlunit/src/user-guide/XMLUnit-Java.xml 2008-03-06 08:49:51 UTC (rev 245) +++ trunk/xmlunit/src/user-guide/XMLUnit-Java.xml 2008-03-07 04:56:39 UTC (rev 246) @@ -456,6 +456,14 @@ or more XML Schema definitions. See <xref linkend="XML Schema Validation"/> for details.</para> + <para>XMLUnit 1.2 introduces a new <literal>Validator</literal> + class that relies on JAXP + 1.3's <literal>javax.xml.validation</literal> package. This + Validator can validate against W3C XML Schema, but may support + different Schema languages like RELAX NG if your JAXP + implementation supports it. See + <xref linkend="JAXP 1.3 Validation"/> for details.</para> + </section> <section id="Xpath Tests"><title>Xpath Tests</title> @@ -2436,7 +2444,7 @@ the configured <literal>EntityResolver</literal> may still be used.</para> - <example> + <example id="schema-jaxp12"> <title>Validating Against a Local XML Schema</title> <programlisting language="Java"><![CDATA[ InputSource is = new InputSource(new FileInputStream(myXmlDocument)); @@ -2500,6 +2508,65 @@ linkend="XML Schema Validation"/>).</listitem> </itemizedlist> </section> + + <section id="JAXP 1.3 Validation"> + <title>JAXP 1.3 Validation</title> + + <para>JAXP 1.3 - shipping with Java5 or better and available as + a separate product for earlier Java VMs - introduces a new + package <ulink url="https://jaxp-sources.dev.java.net/nonav/docs/api/"><literal>javax.xml.validation</literal></ulink> + designed for validations of snippets of XML against different + schema languages. Any compliant implementation must support the + W3C XMl Schema language, but other languages + like <ulink url="http://www.relaxng.org/">RELAX NG</ulink> or + <ulink url="http://www.schematron.com/">Schematron</ulink> may + be supported as well.</para> + + <para>The + class <literal>org.custommonkey.xmlunit.jaxp13.Validator</literal> + can be used to validate a piece of XML against a schema + definition but also to validate the schema definition itself. + By default <literal>Validator</literal> will assume your + definition uses the W3C XML Schema language, but it provides a + constructor that can be used to specify a different language via + an URL supported by the <literal>SchemaFactory</literal> class. + Alternatively you can specify the schema factory itself.</para> + + <para>The schema definition itself can be given via + <literal>Source</literal> elements, just like the pices of XML + to validate are specified as <literal>Source</literal> as + well.</para> + + <para>The following example + uses <literal>org.custommonkey.xmlunit.jaxp13.Validator</literal> + to perform the same type of validation shown in + <xref linkend="schema-jaxp12"/>.</para> + + <example id="schema-jaxp13"> + <title>Validating Against a Local XML Schema</title> + <programlisting language="Java"><![CDATA[ +Validator v = new Validator(); +v.addSchemaSource(new StreamSource(new File(myXmlSchemaFile))); +StreamSource is = new StreamSource(new File(myXmlDocument)); +boolean isValid = v.isInstanceValid(is); +]]></programlisting></example> + + <para>Validating a schema definition is shown in the next + example.</para> + + <example> + <title>Validating a XML Schema Defintion</title> + <programlisting language="Java"><![CDATA[ +Validator v = new Validator(); +v.addSchemaSource(new StreamSource(new File(myXmlSchemaFile))); +boolean isValid = v.isSchemaValid(); +]]></programlisting></example> + + <para>There is no explicit JUnit 3 support + for <literal>org.custommonkey.xmlunit.jaxp13.Validator</literal>.</para> + + </section> + </section> <section id="XPath Tests"> @@ -3259,6 +3326,16 @@ by <literal>Validator</literal> can now be configured completely. <ulink href="https://sourceforge.net/tracker/index.php?func=detail&aid=1903928&group_id=23187&atid=377771">Issue 1903928</ulink>.</listitem> + + <listitem>A new + class <literal>org.custommonkey.xmlunit.jaxp13.Validator</literal> + can be used to validate schema definitions and schema + instances using the <literal>javax.xml.validation</literal> + package of JAXP 1.3. Depending on your JAXP implementation + this may allow you to validate documents against schema + definitions written in RELAX NG or other schema languages in + addition to W3C XML Schema. See + <xref linkend="JAXP 1.3 Validation"/> for details.</listitem> </itemizedlist> </section> Modified: trunk/xmlunit/tests/java/org/custommonkey/xmlunit/jaxp13/test_Validator.java =================================================================== --- trunk/xmlunit/tests/java/org/custommonkey/xmlunit/jaxp13/test_Validator.java 2008-03-06 08:49:51 UTC (rev 245) +++ trunk/xmlunit/tests/java/org/custommonkey/xmlunit/jaxp13/test_Validator.java 2008-03-07 04:56:39 UTC (rev 246) @@ -37,6 +37,7 @@ package org.custommonkey.xmlunit.jaxp13; import java.io.File; +import java.io.IOException; import java.util.Iterator; import java.util.List; import javax.xml.transform.stream.StreamSource; @@ -44,6 +45,9 @@ import junit.framework.TestCase; import org.custommonkey.xmlunit.test_Constants; +import org.custommonkey.xmlunit.exceptions.XMLUnitRuntimeException; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; public class test_Validator extends TestCase { @@ -73,12 +77,81 @@ v.addSchemaSource(new StreamSource(new File(test_Constants.BASEDIR + "/tests/etc/broken.xsd"))); List l = v.getSchemaErrors(); - /* for (Iterator i = l.iterator(); i.hasNext(); ) { - System.err.println(i.next()); + Object ex = i.next(); + assertTrue(ex instanceof SAXParseException); + /* + System.err.println(ex); + */ } - */ assertTrue(l.size() > 0); } + public void testGoodInstanceIsValid() throws Exception { + Validator v = new Validator(); + v.addSchemaSource(new StreamSource(new File(test_Constants.BASEDIR + + "/tests/etc/Book.xsd"))); + StreamSource s = + new StreamSource(new File(test_Constants.BASEDIR + + "/tests/etc/BookXsdGenerated.xml")); + assertTrue(v.isInstanceValid(s)); + } + + public void testBadInstanceIsInvalid() throws Exception { + Validator v = new Validator(); + v.addSchemaSource(new StreamSource(new File(test_Constants.BASEDIR + + "/tests/etc/Book.xsd"))); + StreamSource s = + new StreamSource(new File(test_Constants.BASEDIR + + "/tests/etc/invalidBook.xml")); + assertFalse(v.isInstanceValid(s)); + } + + public void testBadInstanceHasErrors() throws Exception { + Validator v = new Validator(); + v.addSchemaSource(new StreamSource(new File(test_Constants.BASEDIR + + "/tests/etc/Book.xsd"))); + StreamSource s = + new StreamSource(new File(test_Constants.BASEDIR + + "/tests/etc/invalidBook.xml")); + List l = v.getInstanceErrors(s); + for (Iterator i = l.iterator(); i.hasNext(); ) { + Object ex = i.next(); + assertTrue(ex instanceof SAXParseException); + /* + System.err.println(ex); + */ + } + assertTrue(l.size() > 0); + } + + public void testInstanceValidationOfBrokenSchema() { + Validator v = new Validator(); + v.addSchemaSource(new StreamSource(new File(test_Constants.BASEDIR + + "/tests/etc/broken.xsd"))); + StreamSource s = + new StreamSource(new File(test_Constants.BASEDIR + + "/tests/etc/BookXsdGenerated.xml")); + try { + v.isInstanceValid(s); + fail("expected exception because schema is invalid"); + } catch (XMLUnitRuntimeException e) { + assertTrue(e.getCause() instanceof SAXException); + } + } + + public void testInstanceValidationOfMissingFile() { + Validator v = new Validator(); + v.addSchemaSource(new StreamSource(new File(test_Constants.BASEDIR + + "/tests/etc/Book.xsd"))); + StreamSource s = + new StreamSource(new File(test_Constants.BASEDIR + + "/tests/etc/not there.xml")); + try { + v.isInstanceValid(s); + fail("expected exception because instance doesn't exist"); + } catch (XMLUnitRuntimeException e) { + assertTrue(e.getCause() instanceof IOException); + } + } } \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |