views:

226

answers:

1

Hi,

I need to validate XML file against XML Schema so that the schema info is taken from the XML.

I have XML document which defines its namespace. Like this:

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

</myelement>

The schema location is not in the document so I'd need to tell the validator where is the schema for given namespace. Right now I do it the following way:

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware( true );
DocumentBuilder parser = dbf.newDocumentBuilder();
Document document = parser.parse(new File("mydocument.xml"));
String namespace = document.getChildNodes().item(0).getNamespaceURI();
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Source schemaFile = new StreamSource(new File(namespace + ".xsd"));
Schema schema = factory.newSchema(schemaFile);
Validator validator = schema.newValidator();
validator.setErrorHandler(new MyErrorHandler());
validator.validate(new DOMSource(document));

This way it works but it has two problems:

1) It is kind of clumsy that I have to parse the document manually first and create the schema although theoretically validator has all the information it needs to do it automatically.

2) If I validate Document object, I don't get correct line numbers of errors. To get correct line numbers I would have to parse the same document twice (first to get namespace and second to validate).

Does anybody know any better solution?

Is there a way to tell the parser that namespace1 corresponds to schema1.xsd, namespace2 to schema2.xsd etc. before parsing? Or can I write some kind of callback which the parser can use to ask the schema (e.g. I can give LSResourceResolver to SchemaFactory)?

A: 

Currently, there is no way for your parser to validate your document against your schema as the schema isn't available (and the parser isn't even configured to validate your document). To achieve this automatically, I think there are two options:

  1. edit your XML to contain xsi:schemaLocation attribute (not sure if this is supported at all though)

  2. register the schema for your namespace:

Code:

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

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware( true );
dbf.setValidating(true);
dbf.setSchema(schema);
sfussenegger
1. It is possible to get it to work if schemaLocation attribute is present but in my case it is not present and I cannot force to use this attribute. I must be able to validate the document when only namespace is given.2. This way it works but there's my problem. I don't know which schema to use before I have peeked into the XML document.What I'm looking for is a way to tell the parser that namespace1 corresponds to schema1.xsd, namespace2 to schema2.xsd etc. before parsing or an option to write some kind of callback which the parser can use to ask the schema.
martsraits