You are viewing a plain text version of this content. The canonical link for it is here.
Posted to j-dev@xerces.apache.org by bu...@apache.org on 2002/07/31 13:20:19 UTC

DO NOT REPLY [Bug 11326] New: - Parser does not validate if entity resolver is used and XML does not define schemaLocation

DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG 
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://nagoya.apache.org/bugzilla/show_bug.cgi?id=11326>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND 
INSERTED IN THE BUG DATABASE.

http://nagoya.apache.org/bugzilla/show_bug.cgi?id=11326

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

           Summary: Parser does not validate if entity resolver is used and
                    XML does not define schemaLocation
           Product: Xerces2-J
           Version: 2.0.2
          Platform: PC
        OS/Version: Windows XP
            Status: NEW
          Severity: Blocker
          Priority: Other
         Component: SAX
        AssignedTo: xerces-j-dev@xml.apache.org
        ReportedBy: roba@bml.uk.com


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

---------------------------------------------------------------------
To unsubscribe, e-mail: xerces-j-dev-unsubscribe@xml.apache.org
For additional commands, e-mail: xerces-j-dev-help@xml.apache.org