Uploaded image for project: 'Xerces2-J'
  1. Xerces2-J
  2. XERCESJ-412

Parser does not validate if entity resolver is used and XML does not define schemaLocation

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Open
    • Resolution: Unresolved
    • 2.0.2
    • None
    • SAX
    • None
    • Operating System: Windows XP
      Platform: PC
    • 11326

    Description

      We need to assign an entity resolver during parsing, in order to use local
      copies of schema/dtd's, therby, overidding what the user's document is
      dictating.

      A sample XML that I expect to FAIL (You will notice that only a namespace is
      provided here, and that it has a 'BAD' <OrderDate>).

      <?xml version="1.0"?>
      <Order xmlns="urn:schemas-basda-org:2000:purchaseOrder:xdr:3.03">
      <OrderHead>
      <Schema>
      <Version>String</Version>
      </Schema>
      <Parameters>
      <Language>aa_AA</Language>
      <DecimalSeparator>,</DecimalSeparator>
      <Precision>3.14159</Precision>
      </Parameters>
      <OrderType>String</OrderType>
      <OrderCurrency>
      <Currency Code="String">String</Currency>
      </OrderCurrency>
      <Checksum>0</Checksum>
      </OrderHead>
      <OrderDate>BAD-DATE</OrderDate>
      <Supplier>
      <Party>String</Party>
      </Supplier>
      <OrderLine>
      <LineNumber>0</LineNumber>
      </OrderLine>
      </Order>

      -----------------------------------------------------------------------------
      A sample XML that I expect to PASS is...
      ====

      <?xml version="1.0"?>
      <Order xmlns="urn:schemas-basda-org:2000:purchaseOrder:xdr:3.03">
      <OrderHead>
      <Schema>
      <Version>String</Version>
      </Schema>
      <Parameters>
      <Language>aa_AA</Language>
      <DecimalSeparator>,</DecimalSeparator>
      <Precision>3.14159</Precision>
      </Parameters>
      <OrderType>String</OrderType>
      <OrderCurrency>
      <Currency Code="String">String</Currency>
      </OrderCurrency>
      <Checksum>0</Checksum>
      </OrderHead>
      <OrderDate>2001-02-04</OrderDate>
      <Supplier>
      <Party>String</Party>
      </Supplier>
      <OrderLine>
      <LineNumber>0</LineNumber>
      </OrderLine>
      </Order>

      We assign an EntityResolver...

      parser.setProperty("http://apache.org/xml/properties/schema/external-
      schemaLocation", "urn:schemas-basda-org:2000:purchaseOrder:xdr:3.03 order-
      v3.xsd");

      However this appears to turn off validation, even though the entity resolver
      finds the correct document.

      --------------------------------------------------------------------------

      We are also setting the following features: -

      http://xml.org/sax/features/namespaces=true
      http://xml.org/sax/features/namespace-prefixes=false
      http://xml.org/sax/features/validation=true
      http://apache.org/xml/features/validation/schema=true
      http://apache.org/xml/features/validation/schema-full-checking=true
      http://apache.org/xml/features/validation/dynamic=true

      -----------------------------------------------------------------------

      A (Windows - unfortunately) batch to run the test is...

      @echo off
      cls
      echo Bad Order?==========================================================
      java cp lib\xercesImpl.jar;lib\xmlParserAPIs.jar; TestEntityResolver A-BAD
      ORDER.xml
      echo Good Order?==========================================================
      java cp lib\xercesImpl.jar;lib\xmlParserAPIs.jar; TestEntityResolver A-GOOD
      ORDER.xml

      //---------------------------------------------------------------------------

      The java code is....

      import java.io.*;
      import java.net.MalformedURLException;
      import java.net.URL;
      import java.util.Vector;

      import org.xml.sax.*;
      import org.xml.sax.helpers.XMLReaderFactory;

      public class TestEntityResolver implements ErrorHandler, DTDHandler
      {

      private Config config = new Config();
      private Vector errors = new Vector();

      public static void main(String[] args)

      { new TestEntityResolver(args[0]); }

      public TestEntityResolver(String xmlFile)
      {
      try
      {
      XMLReader parser =
      XMLReaderFactory.createXMLReader(
      "org.apache.xerces.parsers.SAXParser");
      TheEntityResolver entResolver =
      new TheEntityResolver("xml/basda/xsd");
      parser.setEntityResolver(entResolver);
      parser.setErrorHandler(this);
      parser.setDTDHandler(this);
      //
      parser.setProperty(
      "http://apache.org/xml/properties/schema/external-
      schemaLocation",
      "urn:schemas-basda-org:2000:purchaseOrder:xdr:3.03 order-
      v3.xsd");
      //
      parser.setFeature("http://xml.org/sax/features/namespaces", true);
      parser.setFeature(
      "http://xml.org/sax/features/namespace-prefixes",
      false);
      parser.setFeature("http://xml.org/sax/features/validation", true);
      parser.setFeature(
      "http://apache.org/xml/features/validation/schema",
      true);
      parser.setFeature(
      "http://apache.org/xml/features/validation/schema-full-
      checking",
      true);
      parser.setFeature(
      "http://apache.org/xml/features/validation/dynamic",
      true);

      parser.parse(
      new InputSource(new FileInputStream(new File(xmlFile))));
      if (errors.size() > 0)

      { throw new Exception(errors.toString()); }

      System.out.println("\n\t\tWOW... Document is valid!!!!\n\n");
      }
      catch (Exception e)

      { System.out.println( "\n\t\tOops - bad document:-\n" + e.getMessage() + "\n\n"); }

      }

      /* (non-Javadoc)

      • @see org.xml.sax.ErrorHandler#error(SAXParseException)
        */
        public void error(SAXParseException exception) throws SAXException { errors.add(exception.getMessage()); }

        /* (non-Javadoc)
        * @see org.xml.sax.ErrorHandler#fatalError(SAXParseException)
        */
        public void fatalError(SAXParseException exception) throws SAXException
        { errors.add(exception.getMessage()); }

      /* (non-Javadoc)

      • @see org.xml.sax.ErrorHandler#warning(SAXParseException)
        */
        public void warning(SAXParseException exception) throws SAXException { errors.add(exception.getMessage()); }

      /* (non-Javadoc)

      • @see org.xml.sax.DTDHandler#notationDecl(String, String, String)
        */
        public void notationDecl(String name, String publicId, String systemId)
        throws SAXException { System.out.println( "DTDHANDLER: notationDecl...name=" + name + " publicId+" + publicId + " systemId+" + systemId); }

      /* (non-Javadoc)

      • @see org.xml.sax.DTDHandler#unparsedEntityDecl(String, String, String,
        String)
        */
        public void unparsedEntityDecl(
        String name,
        String publicId,
        String systemId,
        String notationName)
        throws SAXException { System.out.println( "DTDHANDLER: unparsedEntityDecl...name=" + name + " publicId+" + publicId + " systemId+" + systemId + " notationName=" + notationName); }

      //-------------------------------------------------------------------------
      ------------------------------------------------------------------
      /**

      • This class would normally be from our factory
        */
        class Config
        {

      public String getDocumentDefinitionLocation()

      { return "file:///c:/workspace/qdg/src"; }

      }

      /**

      • the entity resolver
        */
        class TheEntityResolver implements EntityResolver
        {
        public TheEntityResolver(String schemaLocation) { this.schemaLocation = schemaLocation; }

      public InputSource resolveEntity(String publicId, String systemId)
      {
      System.out.println(
      "Resolve publicId=" + publicId + " systemId=" + systemId);
      if (systemId != null && !systemId.equals(""))
      {
      int idx = systemId.lastIndexOf("/");
      String basename = systemId;
      if (idx > -1)
      basename = systemId.substring(idx + 1);
      System.out.println("Basename part of resource is " + basename);

      // First of all, see if we already know about a document
      definition of
      // the same name
      try
      {
      System.out.println(
      "Local Document Definitions are in "
      + config.getDocumentDefinitionLocation());

      // Build a URL for where our local schema's are help. If
      the schema
      // location specified was a URL anyway, then just use
      that, otherwise
      // append the schema location to the default document
      definition
      // location from the general configuration
      URL schemaURL = null;
      if (schemaLocation == null)
      {
      System.out.println(
      "Schema location was not specified. "
      + "Using default of "
      + config.getDocumentDefinitionLocation()
      + "/"
      + basename);
      schemaURL =
      buildURL(
      new String[]

      { config .getDocumentDefinitionLocation() .toString(), basename }

      );
      }
      else
      {
      try

      { schemaURL = new URL(new URL(schemaLocation), basename); System.out.println( "Schema location " + schemaLocation + " is a valid URL"); }

      catch (MalformedURLException murle)
      {
      System.out.println(
      "Schema location is relative, so "
      + "prepending default location ");
      schemaURL =
      buildURL(
      new String[]

      { config .getDocumentDefinitionLocation() .toString(), schemaLocation, basename }

      );
      }
      }

      // Find the resource
      InputStream in = null;
      try
      {
      System.out.println(
      "Looking for " + schemaURL.toExternalForm());
      in = schemaURL.openStream();
      if (in == null)

      { System.out.println( "Failed, trying to open resource " + schemaURL.toExternalForm() + " as a resource."); return null; }

      System.out.println(
      "Opened "
      + schemaURL.toExternalForm()
      + " (SYSTEMID="
      + systemId
      + " PUBLICID="
      + publicId
      + "). Will use this for "
      + basename
      + ".");
      InputSource inSource = new InputSource(in);
      inSource.setSystemId(systemId);
      return inSource;
      }
      // There was no local copy, so revert back to the current
      one
      catch (IOException ioe)

      { System.out.println( "Could not locate a local document " + "definition for " + basename + ". The default " + "of " + systemId + " that was supplied with " + "the original will be used. \n>>>>>>>This **may** " + "not be correct"); return null; }

      finally
      {
      }
      }
      // The config was bad!! sort it out
      catch (MalformedURLException murel)

      { System.out.println( "Could not build a URL for an document " + "definition.\n" + "The default document definition of '" + systemId + "' will be used.\nThis **may** not be correct.\n\n"); return null; }

      }
      else
      return null;
      }

      public URL buildURL(String[] elements) throws MalformedURLException
      {
      StringBuffer buf = new StringBuffer();
      for (int i = 0; i < elements.length; i++)

      { if (i > 0) buf.append("/"); String s = elements[i]; if (s.startsWith("/")) s = s.substring(1); if (s.endsWith("/")) s = s.substring(0, s.length() - 1); buf.append(s); }

      System.out.println("Building URL:" + buf.toString());
      return new URL(buf.toString());
      }

      private String schemaLocation;
      }

      }
      //----------------------------------------------------------------------------

      I have not included the schema here - but they are available from

      http://www.ebis-xml.net/starterpack

      Attachments

        1. ASF.LICENSE.NOT.GRANTED--XDR-compat-v1.xsd
          0.9 kB
          rob anderson
        2. ASF.LICENSE.NOT.GRANTED--TestEntityResolver.java
          11 kB
          rob anderson
        3. ASF.LICENSE.NOT.GRANTED--order-v3.xsd
          46 kB
          rob anderson
        4. ASF.LICENSE.NOT.GRANTED--A-GOOD-ORDER.xml
          0.8 kB
          rob anderson
        5. ASF.LICENSE.NOT.GRANTED--A-BAD-ORDER.xml
          0.6 kB
          rob anderson

        Activity

          People

            Unassigned Unassigned
            roba@bml.uk.com rob anderson
            Votes:
            1 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated: