I have a command line program to validate an XML against an XSD file. One of the command line options for this program is the namespace to use, which is stored in String namespace. I get a different validation result depending on whether I pass the parsed option as namespace or pass the call to namespace.intern(). The different results mean that somewhere in the XML validator the String comparisons performed on namespace have different results, even though they should have the same set of ASCII values.
Is there a fundamental reason why these might produce different comparison results?
The NamespaceFilter class, see below, is where the namespace value is used. This class compares namespace to the value found on the current element inside startElement and then assigns it. startElement is called by the XML reader.
These are the line variations inside validateAgainstXSD:
String.intern()NamespaceFilter nsf = new NamespaceFilter(XMLReaderFactory.createXMLReader(), namespace.intern());
Result:
Validating uart.xml.
NamespaceFilter nsf = new NamespaceFilter(XMLReaderFactory.createXMLReader(), namespace);
Result:
Error at 4: cvc-complex-type.2.4.a: Invalid content was found starting with element 'fileVersion'. One of '{"myNamespace":fileVersion}' is expected.
public static void validateAgainstXSD(File file, File schemaFile, String namespace) {
try {
SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
Schema xsdScheme = factory.newSchema(schemaFile);
Validator validator = xsdScheme.newValidator();
ErrorHandler eh = new DefaultErrorHandler();
validator.setErrorHandler(eh);
// Create namespace replacement filter
NamespaceFilter nsf = new NamespaceFilter(XMLReaderFactory.createXMLReader(), namespace.intern());
// Load the XML source
SAXSource source = new SAXSource(nsf, new InputSource(new FileInputStream(file)));
validator.validate(source, null);
} catch (Exception e) {
e.printStackTrace();
}
}
private static class NamespaceFilter extends XMLFilterImpl {
private String requiredNamespace;
public NamespaceFilter(XMLReader parent) {
super(parent);
}
public NamespaceFilter(XMLReader parent, String namespace) {
this(parent);
requiredNamespace = namespace;
}
@Override
public void startElement(String uri,
String localName,
String qName,
Attributes atts)
throws SAXException {
if (!uri.equals(requiredNamespace)) {
uri = requiredNamespace;
}
super.startElement(uri, localName, qName, atts);
}
}
You need to override endElement() as well, with similar logic in it. Otherwise the start and end element URIs may not match. XMLFilterImpl is probably matching them on == rather than .equals().
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With