0

It seems that the validation is not successful in my following xml.

addressbook.xml

<?xml version ="1.0" encoding="UTF-8"?>

<addressbook>
    <address>
        <name>
            <first-name>Samitha</first-name>
            <last-name>Chathuranga</last-name>
            <sasa>dd</sasa>
        </name>
        <street>107 B</street>
        <village>Poramba</village>
        <city>AG</city>
        <postal-code>80300</postal-code>
        <country>Sri Lanka</country>
    </address>
    <address>
        <name>
            <first-name>Hasara</first-name>
            <last-name>Semini</last-name>
        </name>
        <street>32 A</street>
        <village>Dombanwila</village>
        <city>RG</city>
        <postal-code>34300</postal-code>
        <country>Sri Lanka</country>
    </address>

</addressbook>

I have added the extra element dd to check whether it is validated to the following XSD, but it seems not. No error message comes. So validation seems unsuccessful.

addressbook.xsd

<?xml version="1.0" encoding="UTF-8" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xsd:element name="addressbook">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element ref="address" maxOccurs="unbounded"/>          
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>
    <xsd:element name="address" >
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element ref="name" />
                <xsd:element ref="street" />
                <xsd:element ref="village" />
                <xsd:element ref="city" />
                <xsd:element ref="postal-code" />
                <xsd:element ref="country" />
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>
    <xsd:element name="name">
        <xsd:complexType>
        <xsd:sequence>
            <xsd:element ref="first-name"/>
            <xsd:element ref="last-name"/>
        </xsd:sequence>
    </xsd:complexType>
    </xsd:element>
    <xsd:element name="first-name" type="xsd:string" />
    <xsd:element name="last-name" type="xsd:string" />
    <xsd:element name="street" type="xsd:string" />
    <xsd:element name="village" type="xsd:string" />

    <xsd:element name="city">
        <xsd:simpleType>
            <xsd:restriction base="xsd:string">
                <xsd:length value="2" />
            </xsd:restriction>
        </xsd:simpleType>
    </xsd:element>

    <xsd:element name="postal-code" type="xsd:string" />
    <xsd:element name="country" type="xsd:string" />

</xsd:schema>

What is the reason for it?

Following are the 2 java classes used to do the validation and parsing with SAX.

SAX_XSDValidator.java

//1. Checks for well-formed-ness of the XML with extrnal XML Schema when parsing by SAX Parser.
//2. Validated the XML file with external XML schema Using SAX Parser

// JAXP
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.SAXParser;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.SchemaFactory;

import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;

public class SAX_XSDValidator {
    public static void main(String[] args) {
        try {

            SAXParserFactory factory = SAXParserFactory.newInstance();
            SAXParser parser = factory.newSAXParser();
            XMLReader reader = parser.getXMLReader();
            // checking for well-formed-ness using SAX.=>This doesn't validate
            // against XSD
            // Turn off validation, and turn on namespaces
            factory.setValidating(false);
            factory.setNamespaceAware(true);
            reader.setErrorHandler(new SimpleErrorHandler());
            reader.parse(new InputSource("src/addressbook.xml"));
            System.out.println("Checked well-formed-ness using SAX ");


            // validating using external schema Using SAX Parser
            // SAXParserFactory factory = SAXParserFactory.newInstance();
            factory.setValidating(true);
            factory.setNamespaceAware(true);
            SchemaFactory schemaFactory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
            factory.setSchema(schemaFactory.newSchema(new Source[] { new StreamSource("src/addressbook.xsd") }));
            reader.setErrorHandler(new SimpleErrorHandler());
            reader.parse(new InputSource("src/addressbook.xml"));
            System.out.println("Validation Checked when Parsing with SAX");


            System.out.println("Parsing successful");

        } catch (ParserConfigurationException e) {
            System.out.println("The underlying parser does not support "
                    + " the requested features.");
        } catch (FactoryConfigurationError e) {
            System.out.println("Error occurred obtaining SAX Parser Factory.");
        } catch (Exception e) {
            System.out.println("Caught Exception");
            e.printStackTrace();
        }
    }
}

SimpleErrorHandler.java

import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.ErrorHandler;

public class SimpleErrorHandler implements ErrorHandler {
    public void warning(SAXParseException e) throws SAXException {
        System.out.println(e.getMessage());
    }

    public void error(SAXParseException e) throws SAXException {
        System.out.println(e.getMessage());
    }

    public void fatalError(SAXParseException e) throws SAXException {
        System.out.println(e.getMessage());
    }

}
Samitha Chathuranga
  • 1,689
  • 5
  • 30
  • 57

1 Answers1

1

You need to create a new SAXParser : you're changing the factory variable, but your reader still use the old SAXParser :

// checking for well-formed-ness using SAX.
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setValidating(true);
factory.setNamespaceAware(true);

SAXParser parser = factory.newSAXParser();
XMLReader reader = parser.getXMLReader();

reader.setErrorHandler(new SimpleErrorHandler());
reader.parse(new InputSource("src/addressbook.xml"));
System.out.println("Checked well-formed-ness using SAX ");


// validating using external schema Using SAX Parser
factory.setValidating(false); // set validation to false
SchemaFactory schemaFactory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
factory.setSchema(schemaFactory.newSchema(new Source[] { new StreamSource("src/addressbook.xsd") }));

parser = factory.newSAXParser(); // create a new parser
reader = parser.getXMLReader(); // and refresh your reader

reader.setErrorHandler(new SimpleErrorHandler());
reader.parse(new InputSource("src/addressbook.xml"));
System.out.println("Validation Checked when Parsing with SAX");


System.out.println("Parsing successful");
zessx
  • 68,042
  • 28
  • 135
  • 158
  • Thanks a lot. The problem is solved by it. But I have a question.. Why do you set factory.setValidating(false). Actually what is happened by setting it true or false? When I set it to true above an error comes as "Document is invalid: no grammar found. Document root element "addressbook", must match DOCTYPE root "null"." How can the document be invalid due to the reason that it has not referenced a DOCTYPE ? – Samitha Chathuranga May 15 '14 at 11:09
  • `setValidating()` will validate your XML by looking for a DTD (a grammar). But here, you're using a XSD, not a DTD, then you must disable this validation. The "real" validation is brought by the `setSchema()` function. ([source](http://docs.oracle.com/javase/7/docs/api/javax/xml/parsers/SAXParserFactory.html#setValidating(boolean))) – zessx May 15 '14 at 11:22
  • But I have another question.. In the first part "// checking for well-formed-ness using SAX.=>This doesn't validate against XSD" when I give setValidating(true) above ""Document is invalid: no grammar found. Document root element "addressbook", must match DOCTYPE root "null"." error doesn't come. No error comes at all actually. So it is rather conflicting with ur above explanation..!!! – Samitha Chathuranga May 16 '14 at 05:13
  • As long as you don't set a `Schema`, SAX won't check the validity. – zessx May 16 '14 at 12:49
  • U didn't get my question correctly. My problem is that eventhough I give setValidating(true) in the first part, that aforementioned error doesn't come? I haven't det a DTD. SO according to your previous explanation as I haven't give a DTD, there should come an error.. What is the case here...? – Samitha Chathuranga May 18 '14 at 17:15
  • Same thing, you're calling `setValidating(true)` **after** calling `factory.newSAXParser()`. I edited my answer to give you the full code. – zessx May 19 '14 at 07:26