2010-03-12 15 views
6

Kürzlich haben wir unsere Projekte auf Java 1.6 umgestellt. Bei der Ausführung der Tests habe ich festgestellt, dass mit 1.6 keine SAXParseException geworfen wird, die mit 1.5 geworfen wurde.Unterschied in DocumentBuilder.parse bei Verwendung von JRE 1.5 und JDK 1.6

Unten ist mein Testcode, um das Problem zu demonstrieren.

import java.io.StringReader; 

import javax.xml.parsers.DocumentBuilder; 
import javax.xml.parsers.DocumentBuilderFactory; 
import javax.xml.transform.stream.StreamSource; 
import javax.xml.validation.SchemaFactory; 

import org.junit.Test; 
import org.xml.sax.InputSource; 
import org.xml.sax.SAXParseException; 


/** 
* Test class to demonstrate the difference between JDK 1.5 to JDK 1.6. 
* 
* Seen on Linux: 
* 
* <pre> 
* #java version "1.6.0_18" 
* Java(TM) SE Runtime Environment (build 1.6.0_18-b07) 
* Java HotSpot(TM) Server VM (build 16.0-b13, mixed mode) 
* </pre> 
* 
* Seen on OSX: 
* 
* <pre> 
* java version "1.6.0_17" 
* Java(TM) SE Runtime Environment (build 1.6.0_17-b04-248-10M3025) 
* Java HotSpot(TM) 64-Bit Server VM (build 14.3-b01-101, mixed mode) 
* </pre> 
* 
* @author dhiller (creator) 
* @author $Author$ (last editor) 
* @version $Revision$ 
* @since 12.03.2010 11:32:31 
*/ 
public class TestXMLValidation { 

    /** 
    * Tests the schema validation of an XML against a simple schema. 
    * 
    * @throws Exception 
    *   Falls ein Fehler auftritt 
    * @throws junit.framework.AssertionFailedError 
    *   Falls eine Unit-Test-Pruefung fehlschlaegt 
    */ 
    @Test(expected = SAXParseException.class) 
    public void testValidate() throws Exception { 
    final StreamSource schema = new StreamSource(new StringReader("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" 
     + "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" " 
     + "elementFormDefault=\"qualified\" xmlns:xsd=\"undefined\">" + "<xs:element name=\"Test\"/>" + "</xs:schema>")); 
    final String xml = "<Test42/>"; 
    final DocumentBuilderFactory newFactory = DocumentBuilderFactory.newInstance(); 
    newFactory.setSchema(SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema").newSchema(schema)); 
    final DocumentBuilder documentBuilder = newFactory.newDocumentBuilder(); 
    documentBuilder.parse(new InputSource(new StringReader(xml))); 
    } 

} 

Wenn ein JVM 1.5 den Test mit gibt, auf 1.6 mit "Expected Ausnahme SAXParseException" schlägt fehl.

Die Javadoc der DocumentBuilderFactory.setSchema(Schema) Methode sagt:

Wenn Fehler durch die Validator gefunden werden, der Parser verantwortlich ist sie an den vom Benutzer angegebenen zu berichten Fehlerbehandler (oder wenn der Handler Fehler ist nicht gesetzt, ignoriere sie oder wirf sie), genau wie alle anderen Fehler vom Parser selbst gefunden. In anderen Worten, wenn der Benutzer angegebenen Fehlerbehandler gesetzt ist, muss es diese Fehler erhalten, und wenn nicht, müssen sie nach den spezifischen Standardfehler Behandlungsregeln Implementierung behandelt werden.

Die Javadoc der DocumentBuilder.parse(InputSource) Methode sagen:

BTW: Ich habe versucht, über setErrorHandler ein Fehlerhandler Einstellung, aber es gibt nach wie vor keine Ausnahme.

Nun meine Frage:

Was auf 1,6 geändert hat, der die Schema-Validierung verhindert, dass ein SAXParseException zu werfen? Bezieht es sich auf das Schema oder auf das XML, das ich analysieren wollte?

Update:

Der folgende Code funktioniert auf 1.5 und 1.6, wie ich habe den Wunsch worden:

@Test(expected = SAXParseException.class) 
    public void testValidate() throws Exception { 
    final StreamSource schema = new StreamSource(new StringReader("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" 
     + "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" " 
     + "elementFormDefault=\"qualified\" xmlns:xsd=\"undefined\">" + "<xs:element name=\"Test\"/>" + "</xs:schema>")); 
    final String xml = "<Test42/>"; 
    final DocumentBuilderFactory newFactory = DocumentBuilderFactory.newInstance(); 
    final Schema newSchema = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema").newSchema(schema); 
    newFactory.setSchema(newSchema); 
    final Validator newValidator = newSchema.newValidator(); 
    final Source is = new StreamSource(new StringReader(xml)); 
    try { 
     newValidator.validate((Source) is); 
    } 
    catch (Exception e) { 
     e.printStackTrace(); 
     throw e; 
    } 
    final DocumentBuilder documentBuilder = newFactory.newDocumentBuilder(); 
    documentBuilder.parse(new InputSource(new StringReader(xml))); 
    } 

Die Lösung scheint eine Validator-Instanz aus dem Schema Instanz erstellt, um explizit zu verwenden . Ich habe die Lösung here

Noch finde ich bin nicht sicher, warum das so ist ...

Antwort

1

Offenbar ein Dokument mit dem Schema nicht nur verdient ein milder Tadel auf stderr aus der Standard-Fehlerbehandlung entsprechen. Meine Lösung bestand darin, den Standardfehlerhandler durch einen strengeren zu ersetzen:

// builder is my DocumentBuilder 
builder.setErrorHandler(new ErrorHandler() { 
    @Override 
    public void error(SAXParseException arg0) throws SAXException { 
     throw arg0;    
    } 

    @Override 
    public void fatalError(SAXParseException arg0) throws SAXException { 
     throw arg0;     
    } 

    @Override 
    public void warning(SAXParseException arg0) throws SAXException { 
     throw arg0;     
    } 
});