11

I want to validate an XML file against an XSD schema. The XML files root element does not have any namespace or xsi details. It has no attributes so just <root>.

I have tried the following code from http://www.ibm.com/developerworks/xml/library/x-javaxmlvalidapi.html with no luck as I receive cvc-elt.1: Cannot find the declaration of element 'root'

SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");

File schemaFile = new File("schema.xsd");

Schema xsdScheme = factory.newSchema(schemaFile);

Validator validator = xsdScheme.newValidator();

Source source = new StreamSource(xmlfile);

validator.validate(source);

The xml validates fine with the namespace headers included etc (added via xmlspy), but I would have thought the xml namespace could be declared without having to manually edit the source file?

Edit and Solution:

public static void validateAgainstXSD(File file) {

    try {
        SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");

        File schemaFile = new File("path/to/xsd");

        Schema xsdScheme = factory.newSchema(schemaFile);

        Validator validator = xsdScheme.newValidator();

        SAXSource source = new SAXSource(
                new NamespaceFilter(XMLReaderFactory.createXMLReader()),
                new InputSource(new FileInputStream(file)));

        validator.validate(source,null);

    } catch (Exception e) {
        e.printStackTrace();
    }

}

protected static class NamespaceFilter extends XMLFilterImpl {

    String requiredNamespace = "namespace";

    public NamespaceFilter(XMLReader parent) {
        super(parent);
    }

    @Override
    public void startElement(String arg0, String arg1, String arg2, Attributes arg3) throws SAXException {
        if(!arg0.equals(requiredNamespace)) 
            arg0 = requiredNamespace;
        super.startElement(arg0, arg1, arg2, arg3);
    }       
}
ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
Alec Holmes
  • 3,625
  • 4
  • 22
  • 23

1 Answers1

2

You have two separate concerns you need to take care of:

  1. Declaring the namespace that your document uses.
  2. Putting an xsi:schemaLocation attribute in the file to give a hint (!) where the schema is.

You can safely skip the second part, as the location is really only a hint. You cannot skip the first part. The namespace declared in the XML file is matched against the schema. Important, this:

<xml> ... </xml>

Is not the same as this:

<xml xmlns="urn:foo"> ... </xml>

So you need to declare your namespace in the XML document, otherwise it will not correspond to your schema and you will get this error.

xcut
  • 6,219
  • 1
  • 33
  • 27
  • 2
    The xml document is created by a third party, they may not have added the correct namespace, is there a way in java to easily append this namespace to the root xml element before validating? – Alec Holmes Jun 08 '10 at 12:14
  • 2
    There are two things you can do about this: 1. insert it using string manipulation if you know what you're doing and the format is quite static or better 2. create a SAX filter that changes the namespace (see http://www.saxproject.org/filters.html), and pass the filter to the Validator. I have not tried that with a Validator object, but hopefully it will work. – xcut Jun 08 '10 at 12:43
  • 1
    Thanks xcut. I researched about filters and it works execellently. For others see the solution in my original post above. – Alec Holmes Jun 09 '10 at 15:48