简体   繁体   中英

Why do I get different results with String.intern() vs. passing String object in Java?

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.

String object as is

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.

Source in context

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().

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM