....
In the meantime heres the root cause of my most recent heartache....
The solution is ...
String xml ="<envelope><header2>Hi</header2></envelope>";
String xsd = "http://localhost:8080/xml/test.xsd";
SAXBuilder builder = new SAXBuilder("org.apache.xerces.parsers.SAXParser", true);
builder.setFeature("http://apache.org/xml/features/validation/schema", true);
builder.setProperty("http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation",xsd);
builder.setValidation(true);
builder.build(new InputSource(new StringReader(xml)));
Simple isn't it
What could have been the problem?
The problem is that innocuous line
builder.setProperty("http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation",xsd);
To cut a long story short Xerces has 2 modes for validating external schemas (i.e. not the schemas referenced in the Xml doc itself). 1/ Namespace enabled 2/ No Namespace.
Simple huh?
Well it is once you know that simple fact. I on the other hand didn't . (Mind you I do think it should be possbile to validate an arbitary Xml doc without necessarily knowing if its namespace enabled or not. But thats for another day)
So in summary people
If you want to avoid cryptic exceptions like
org.jdom.input.JDOMParseException: Error on line 1: cvc-elt.1: Cannot find the declaration of element 'envelope'.
at org.jdom.input.SAXBuilder.build(SAXBuilder.java:466)
at XmlTest.main(XmlTest.java:41)
Caused by: org.xml.sax.SAXParseException: cvc-elt.1: Cannot find the declaration of element 'envelope'.
.....
NB. This is the same exception you get if Xerces cannot locate your schema file, or if you don't configure the paramerters correctly. Something more intuitive would be more helpful.
do the following
1/ If your Xml doc uses namespaces
String xml ="<envelope><header2>Hi</header2></envelope>";
// Namespae of xsd1
String ns1 = "http://www.w3.org/2001/12/soap-envelope"
String xsd1 = "http://localhost:8080/xml/test.xsd";
//Namespace of xsd2
String ns2 = "http://kevinj.develop.com/weblog/weblog.xsd";
String xsd2 = "http://localhost:8080/xml/test2.xsd";
SAXBuilder builder = new SAXBuilder("org.apache.xerces.parsers.SAXParser", true);
builder.setFeature("http://apache.org/xml/features/validation/schema", true);
builder.setProperty(
"http://apache.org/xml/properties/schema/external-schemaLocation", ns1+" "+xsd1+" + ns2+" "+xsd2);
builder.setValidation(true);
builder.build(new InputSource(new StringReader(xml)));
You must set the Property
http://apache.org/xml/properties/schema/external-schemaLocation
with a space seperated String list of the schema(s) to validate against.The list takes the following form namespace uri namespace uri .... Its composed of pairs of values, the namespace that the schema will validate and the actual location of the schema file. (It can be any uri http://, file:// etc)
This section is taken from the JDOM FAQ
Schema locations are given by setting the property "http://apache.org/xml/properties/schema/external-schemaLocation" to a list of whitespace separated name-value pairs. The 'name' is the namespace the schema is associated with, the 'value' is the location of the schema for that namespace. For example:
The above example shows how to validate against multiple schemas -- against the SOAP 1.2 schema where the namespace is http://www.w3.org/2001/12/soap-envelope and the and against a schema for namespace http://kevinj.develop.com/weblog/weblog.xsd. The files describing these schemas are in soap-envelope.xsd and weblog.xsd respectively. You can add as many of these name value pairs as necessary. The values themselves are URLs. The name value pairs follow the meaning given in the Schema recommendation (http://www.w3.org/TR/xmlschema-1/#schema-loc ). |
2/ If your Xml doc does not use namespaces
String xml ="<envelope><header2>Hi</header2></envelope>";
String xsd = "http://localhost:8080/xml/test.xsd";
SAXBuilder builder = new SAXBuilder("org.apache.xerces.parsers.SAXParser", true);
builder.setFeature("http://apache.org/xml/features/validation/schema",true);
builder.setProperty("http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation",xsd);
builder.build(new InputSource(new StringReader(xml)));
Here we set the property
http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation
(spot the difference) with simply the schema uri. (Not a List as there is only the default namespace) to validate against, and only a single items since there is no namespaces, (i.e. not a pair like before)It may look simple but that wee little problem had me stumped for longer than I'd care to mention.
Heres some links on the stuff
The Jdom faq Jdom uses xerces so this applies to xerces as well.
xerces bugzilla entry. There was a bug with this prior to version 2.2.0
One aside. By default xerces will not throw exceptions for validation failures, the parser must be configured to do that.
Jdom will configure the parser to do this by default. (for a lazy programmer like me this simply means that I use jdom to wrap my calls to xerces, rather than actually looking up how to configure xerces)
14 comments:
Hi K,
You saved my life ... well at least my weekend ;-) Thanks for these tips!
Chris
Thanks a bunch, I was about to express my rage in unhealthy (to others) ways before I found this post. Now it's time to get drunk!
Hi,
I had followed the steps as mentioned but for me it is throwing JDOMException, mentioning that "the property is not recognized for SAX driver".
Please may i now which version of jdom jar file you have used..
thanks in advance,
Meena.
I've used lots of different jdom versions. I would urge you to check the JDOM faq at http://www.jdom.org/docs/faq.html#a0360
It says all versions above 0.8 Beta should work.
Also check your configuration. For me there's always a possiblity I've done something daft. Are you using xerces under jdom? Is that configured correctly (ie. can you parse a simple xml doc without validation)?
Once you know that is working then start to track down why the validation isn't working. Are your schema urls correct? (Can you use a browser to access them?)
Hi K,
Thank you for your immediate reply..
I had checked in jdom faq, they mentioned that xerces 2 and above will support schema validation so i used jdom 1.0 xerces 2.7.1 previously, it didn't work, but now i'm using jdom 1.0 and xerces 2.8.0. It started working.
Thanks a lot for helping:-)
Meena.
Hi russ,
Have you specified the schema location and schema name in the root element. Also check the namespace. I think you may commited mistake in that.Have you checked the version of the jar file.
thanks and regards,
Meena.
Hi, I had also this kind of problem when validating XML with XSD and with help of your article I have solved it. But I used standalone XSD with no namespace.
Now I have XSD which is importing another XSD which contains some common data types. In Netbeans IDE I debugged it - so schemas are valid. But I got the very known exception:
org.xml.sax.SAXParseException: cvc-elt.1: Cannot find the declaration of element 'SecDb'.
This is that root element in XML:
<SecDb xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.w3.org/2001/XMLSchema AppRepository2.xsd http://url/ns/something dataTypes.xsd">
That XMLSchema namesepace is targetNamespace in AppRepository2.xsd and http://url/ns/something is targetNamespace in dataTypes.xsd.
Can someone help?
I just wanted to thank you for your explanations. I was struggling with this, and you helped me resolve my issue.
Thanks.
Ou yeah!!! It's work!!!)))
Thank you very much.
Hello,
I receive the same error, but I can not solve it... I don't use a builder where I can set the Property.
The code:
FileOutputStream fileOutputStream=new FileOutputStream("C: /xml/catalogueSAX.xml");
OutputFormat outputFormat=new OutputFormat("XML","ISO-8859-1",false);
outputFormat.setIndent(0);
XMLSerializer xmlSerializer=new XMLSerializer(fileOutputStream,outputFormat);
ContentHandler contentHandler= xmlSerializer.asContentHandler();
String language=XMLConstants.W3C_XML_SCHEMA_NS_URI;
SchemaFactory schemaFactory=SchemaFactory.newInstance(language);
final String OUR_SCHEMA="C:/xmlfiles/catalogueBig.xsd";
Source schemaFile=new StreamSource(new FileInputStream(OUR_SCHEMA));
Schema schema=schemaFactory.newSchema(schemaFile);
ValidatorHandler validatorForSaxHandler=schema.newValidatorHandler();
validatorForSaxHandler.setErrorHandler(new ErrorHandlerImpl());
validatorForSaxHandler.setContentHandler(contentHandler);
Catalogue catalogue=getCatalogue(10,10);
validatorForSaxHandler.startDocument();
validatorForSaxHandler.startElement("", "", "catalogue", new AttributesImpl());
....
validatorForSaxHandler.endElement("", "", "catalogue");
validatorForSaxHandler.endDocument();
Does somebody know how to solve this error:
org.xml.sax.SAXParseException: cvc-elt.1: Cannot find the declaration of element 'catalogue'.
Thanks in advance!
It is some bug and normally it it solved in jdk 1.5
see http://mail-archives.apache.org/mod_mbox/xerces-j-dev/200605.mbox/%3c3262346.1146854608199.JavaMail.jira@brutus%3e
But I tried to use jdk 1.5 and I still receive this error!
Is there somebody who knows what to do?
Thanks!
Thanks! it did save me a long time... hopefully this issues will fade away as the language becomes more elegant....
Kind Regards
Alejandro
Thank you very much. Thx to your advice I could fix my problem very fast.
Many thanks! I didn't manage to understand this "couples" (namespace,xsd-file). What a headhache!
Post a Comment