[Practicalxml-commits] SF.net SVN: practicalxml:[31] trunk/src
                
                Brought to you by:
                
                    kdgregory
                    
                
            
            
        
        
        
    | 
      
      
      From: Auto-Generated S. C. M. <pra...@li...> - 2008-10-12 16:57:17
      
     | 
| Revision: 31
          http://practicalxml.svn.sourceforge.net/practicalxml/?rev=31&view=rev
Author:   kdgregory
Date:     2008-10-12 16:57:10 +0000 (Sun, 12 Oct 2008)
Log Message:
-----------
ParseUtil: add schema validation
Modified Paths:
--------------
    trunk/src/main/java/net/sf/practicalxml/ParseUtil.java
    trunk/src/test/java/net/sf/practicalxml/TestParseUtil.java
Modified: trunk/src/main/java/net/sf/practicalxml/ParseUtil.java
===================================================================
--- trunk/src/main/java/net/sf/practicalxml/ParseUtil.java	2008-10-12 13:05:05 UTC (rev 30)
+++ trunk/src/main/java/net/sf/practicalxml/ParseUtil.java	2008-10-12 16:57:10 UTC (rev 31)
@@ -6,6 +6,7 @@
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.validation.Schema;
 
 import net.sf.practicalxml.misc.ExceptionErrorHandler;
 
@@ -119,10 +120,40 @@
     public static Document validatingParse(
             InputSource source, ErrorHandler errHandler)
     {
-        return validatingParse(source, null, errHandler);
+        return validatingParse(source, (EntityResolver)null, errHandler);
     }
 
 
+    /**
+     *  Parses the supplied source with a namespace-aware, XSD-validating
+     *  parser, using a caller-supplied error handler and entity resolver.
+     *  Both of these objects may be <code>null</code>, to use the built-in
+     *  defaults.
+     *
+     *  @throws XmlException for any configuration or fatal execution error.
+     */
+    public static Document validatingParse(
+            InputSource source, Schema schema, ErrorHandler errHandler)
+    {
+        DocumentBuilder db = newXSDDocumentBuilder(schema);
+        if (errHandler != null)
+            db.setErrorHandler(errHandler);
+
+        try
+        {
+            return db.parse(source);
+        }
+        catch (IOException e)
+        {
+            throw new XmlException("unable to parse", e);
+        }
+        catch (SAXException e)
+        {
+            throw new XmlException("unable to parse", e);
+        }
+    }
+
+
 //----------------------------------------------------------------------------
 //  Internals
 //----------------------------------------------------------------------------
@@ -134,6 +165,9 @@
     private static DocumentBuilderFactory _dtdDbf;
 
 
+    /**
+     *  Returns a namespace-aware, non-validating parser.
+     */
     private static synchronized DocumentBuilder newNVDocumentBuilder()
     {
         if (_nvDbf == null)
@@ -155,6 +189,9 @@
     }
 
 
+    /**
+     *  Returns a namespace-aware, DTD-validating parser.
+     */
     private static synchronized DocumentBuilder newDTDDocumentBuilder()
     {
         if (_dtdDbf == null)
@@ -174,4 +211,28 @@
             throw new XmlException("unable to confiure parser", e);
         }
     }
+
+
+    /**
+     *  Returns a namespace-aware, XSD-validating parser using the supplied
+     *  schema. Note that we don't use a singleton factory, because the schema
+     *  gets applied to the factory, not the parser.
+     */
+    private static synchronized DocumentBuilder newXSDDocumentBuilder(Schema schema)
+    {
+        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+        dbf.setNamespaceAware(true);
+        dbf.setValidating(false);
+        dbf.setCoalescing(true);
+        dbf.setSchema(schema);
+
+        try
+        {
+            return _dtdDbf.newDocumentBuilder();
+        }
+        catch (ParserConfigurationException e)
+        {
+            throw new XmlException("unable to confiure parser", e);
+        }
+    }
 }
Modified: trunk/src/test/java/net/sf/practicalxml/TestParseUtil.java
===================================================================
--- trunk/src/test/java/net/sf/practicalxml/TestParseUtil.java	2008-10-12 13:05:05 UTC (rev 30)
+++ trunk/src/test/java/net/sf/practicalxml/TestParseUtil.java	2008-10-12 16:57:10 UTC (rev 31)
@@ -5,6 +5,11 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import javax.xml.XMLConstants;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.Text;
@@ -30,7 +35,43 @@
     + "<!ATTLIST foo name CDATA #REQUIRED>";
 
 
+    /** An XSD that replicates the DTD above */
+    private final static String BASIC_XSD
+    = "<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">"
+    +   "<xsd:element name=\"foo\" type=\"FooType\"/>"
+    +   "<xsd:complexType name=\"FooType\">"
+    +     "<xsd:sequence>"
+    +       "<xsd:element name=\"bar\" type=\"xsd:string\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>"
+    +       "<xsd:element name=\"baz\" minOccurs=\"1\" maxOccurs=\"unbounded\">"
+    +          "<xsd:complexType>"
+    +          "</xsd:complexType>"
+    +       "</xsd:element>"
+    +     "</xsd:sequence>"
+    +     "<xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\"/>"
+    +   "</xsd:complexType>"
+    + "</xsd:schema>";
+
+
     /**
+     *  Creates a <code>Schema</code> object from source XML. We could use
+     *  {@link SchemaUtil}, but I'd like this test to be as self-contained
+     *  as possible.
+     */
+    private static Schema createSchema(String xsd)
+    {
+        try
+        {
+            SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+            return sf.newSchema(new StreamSource(new StringReader(xsd)));
+        }
+        catch (Exception e)
+        {
+            throw new RuntimeException(e);
+        }
+    }
+
+
+    /**
      *  An ErrorHandler that records its invocations, and provides asserts
      *  on them.
      */
@@ -63,38 +104,8 @@
             assertEquals("TestErrorHandler warnings", numWarnings, warnings.size());
         }
     }
-    
-    
-    /**
-     *  An EntityResolver that will resolve a single entity.
-     */
-    private static class TestEntityResolver
-    implements EntityResolver
-    {
-        private String _publicId;
-        private String _systemId;
-        private String _content;
-        
-        public TestEntityResolver(String publicId, String systemId, String content)
-        {
-            _publicId = publicId;
-            _systemId = systemId;
-            _content = content;
-        }
 
-        public InputSource resolveEntity(String publicId, String systemId)
-        throws SAXException, IOException
-        {
-            if (((publicId == null) || publicId.equals(_publicId))
-                    && ((systemId == null) || systemId.equals(_systemId)))
-            {
-                return new InputSource(new StringReader(_content));
-            }
-            return null;
-        }
-    }
 
-
 //----------------------------------------------------------------------------
 //  Test Cases
 //----------------------------------------------------------------------------
@@ -229,13 +240,40 @@
         +     "<baz/>"
         + "</foo>";
 
+        EntityResolver resolver = new EntityResolver()
+        {
+            public InputSource resolveEntity(String publicId, String systemId)
+            throws SAXException, IOException
+            {
+                return new InputSource(new StringReader(BASIC_DTD));
+            }
+        };
         TestErrorHandler errHandler = new TestErrorHandler();
-        TestEntityResolver resolver = new TestEntityResolver(null, "test", BASIC_DTD);
         Document doc = ParseUtil.validatingParse(
                             new InputSource(new StringReader(xml)),
-                            resolver, errHandler);
+                            resolver,
+                            errHandler);
 
         assertEquals("foo", doc.getDocumentElement().getTagName());
         errHandler.assertResults(0, 0, 0);
     }
+
+
+    public void testValidDocumentWithSchema() throws Exception
+    {
+        String xml
+        = "<foo name='zippy'>"
+        +     "<bar>something here</bar>"
+        +     "<baz/>"
+        + "</foo>";
+
+        TestErrorHandler errHandler = new TestErrorHandler();
+        Document doc = ParseUtil.validatingParse(
+                            new InputSource(new StringReader(xml)),
+                            createSchema(BASIC_XSD),
+                            errHandler);
+
+        assertEquals("foo", doc.getDocumentElement().getTagName());
+        errHandler.assertResults(0, 0, 0);
+    }
 }
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
 |