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