Validate XML against Schema

P

Paco

I'm trying to validate some XML against a schema. The code I have
works but it won't give me any useful information for where the error
is in the XML. I can get useful information (line numbers) if there
are problems when loading the schema and XML. However, the exceptions
generated from validate() always have line and column numbers of "-1".
Am I doing something wrong or should I be going about this in a totally
different method? My code is below (minus error handling and such).
The SAXErrorHandler is a class I created that simply prints out the
message and line and column numbers.

// Load Schema
File schemaFile = new File("schema.xsd");
SchemaFactory factory =
SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Source schemaSource = new StreamSource(schemaFile);
Schema schema = factory.newSchema(schemaSource);

// Load XML
File xmlFile = new File("data.xml");
DocumentBuilder parser =
DocumentBuilderFactory.newInstance().newDocumentBuilder();
document = parser.parse(xmlFile);

// Validate
Validator validator = schema.newValidator();
SAXErrorHandler errHandler = new SAXErrorHandler();
validator.setErrorHandler(errHandler);
DOMResult result = new DOMResult();
validator.validate(new DOMSource(document), result);
 
R

robert

Paco escreveu:
I'm trying to validate some XML against a schema. The code I have
works but it won't give me any useful information for where the error
is in the XML. I can get useful information (line numbers) if there
are problems when loading the schema and XML. However, the exceptions
generated from validate() always have line and column numbers of "-1".
Am I doing something wrong or should I be going about this in a totally
different method? My code is below (minus error handling and such).
The SAXErrorHandler is a class I created that simply prints out the
message and line and column numbers.

// Load Schema
File schemaFile = new File("schema.xsd");
SchemaFactory factory =
SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Source schemaSource = new StreamSource(schemaFile);
Schema schema = factory.newSchema(schemaSource);

// Load XML
File xmlFile = new File("data.xml");
DocumentBuilder parser =
DocumentBuilderFactory.newInstance().newDocumentBuilder();
document = parser.parse(xmlFile);

// Validate
Validator validator = schema.newValidator();
SAXErrorHandler errHandler = new SAXErrorHandler();
validator.setErrorHandler(errHandler);
DOMResult result = new DOMResult();
validator.validate(new DOMSource(document), result);

You could define your own Handler that extends DefaultHandler to get
into error details - you should have more luck than -1. You don't show
your class but implementing DefaultHandler is a good place to start.
The point being that there are other handlers - see the sax2 o'reilly
book or google for more info. The entityResolver shown is for locally
resolving URI's and is probably not relevant:

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setValidating(true);
dbf.setNamespaceAware(true);
dbf.setAttribute(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA);
DocumentBuilder db = dbf.newDocumentBuilder();
//Add a custom error handler
MyDefaultHandler dh = new MyDefaultHandler();
db.setErrorHandler(dh);
db.setEntityResolver(new SchemaLoader());
InputSource isXml = new InputSource (new StringReader(xml));
Document doc_in = db.parse(isXml);
if (false == dh.isSchemaValidated)
{
throw new java.lang.IllegalStateException("ERR: Invalid XML
received - schema validation failed");
}

//Custom error hanler to print errors and return isValid
class MyDefaultHandler extends DefaultHandler
{
//flag to check if the xml document was valid
public boolean isSchemaValidated = true;

//Receive notification of a recoverable error.
public void error(SAXParseException se)
{
setValidity(se);
}

//Receive notification of a non-recoverable error.
public void fatalError(SAXParseException se)
{
setValidity(se);
}

//Receive notification of a warning.
public void warning(SAXParseException se)
{
setValidity(se);
}

private void setValidity(SAXParseException se)
{
isSchemaValidated = false;
Fwlog.error(this, Fwlog.DB, se);
}
}

Now if your SAXParseException trace shows -1, than I advice with going
with a different jar implementation in the classloader.

HTH,
Robert
http://www.braziloutsource.com/
 
P

Paco

Thanks for the response Robert. My problem does stem from
SAXParseException returning -1.

Here is the code from my handler:

public void error(SAXParseException e)
{
System.out.println("ERROR:\n"
+ " EXCEPTION: " + e.getMessage() + "\n"
+ " LINE NUM: " + e.getLineNumber() + "\n"
+ " COL NUM: " + e.getColumnNumber() + "\n");
}


Here is a typical exception:

ERROR:
EXCEPTION: cvc-complex-type.2.4.a: Invalid content was found starting
with element 'Stuff'. One of '{"":Name}' is expected.
LINE NUM: -1
COL NUM: -1


I'm working with jdk1.5.0_05. Is there another way to go about this?
Should I use a Locator, not use a DOMSource, or what? Even if I could
just get access to the Node that violated the schema, that would be an
improvement.

Thanks,
Paco
 
M

Mike Schilling

Paco said:
Thanks for the response Robert. My problem does stem from
SAXParseException returning -1.

Here is the code from my handler:

public void error(SAXParseException e)
{
System.out.println("ERROR:\n"
+ " EXCEPTION: " + e.getMessage() + "\n"
+ " LINE NUM: " + e.getLineNumber() + "\n"
+ " COL NUM: " + e.getColumnNumber() + "\n");
}


Here is a typical exception:

ERROR:
EXCEPTION: cvc-complex-type.2.4.a: Invalid content was found starting
with element 'Stuff'. One of '{"":Name}' is expected.
LINE NUM: -1
COL NUM: -1


I'm working with jdk1.5.0_05. Is there another way to go about this?
Should I use a Locator, not use a DOMSource, or what? Even if I could
just get access to the Node that violated the schema, that would be an
improvement.

I don't see how the validator could get line/column information from a
DOMSource. DOM nodes don't contain that information. (It's possible that
some DOM Node implementations do, but there's no uniform way to access that
information.) It's worth trying a SAXSource instead.
 
P

Paco

Thanks Mike. A SAXSource does give me the correct information.
However, I need the results of the validation to be a DOM type object.
Does anyone know how to transform a SAXResult into a DOMResult?

Thanks,
Paco
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,898
Latest member
BlairH7607

Latest Threads

Top