2010-03-12 18 views
6

Nous avons récemment passé nos projets à Java 1.6. Lors de l'exécution des tests, j'ai découvert qu'en utilisant 1.6 une exception SAXParseException n'a pas été levée en utilisant 1.5.Différence dans DocumentBuilder.parse lors de l'utilisation de JRE 1.5 et JDK 1.6

Ci-dessous est mon code de test pour démontrer le problème.

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))); 
    } 

} 

Lorsque vous utilisez une machine virtuelle Java 1.5 passe le test, le 1.6, il échoue avec "exception attendue SAXParseException".

Le Javadoc de la DocumentBuilderFactory.setSchema(Schema) Méthode dit:

Lorsque des erreurs sont détectées par le validateur, l'analyseur est responsable de les signaler à l' spécifié par l'utilisateur ErrorHandler (ou si le gestionnaire d'erreurs est pas défini, ignorez-les ou lancez-les eux), comme toutes les autres erreurs trouvées par l'analyseur lui-même. En d'autres mots , si le ErrorHandler spécifié par l'utilisateur est défini, il doit recevoir ces erreurs, et sinon, ils doivent être traités selon l'erreur par défaut spécifique mise en œuvre règles de gestion.

Le Javadoc de la méthode DocumentBuilder.parse(InputSource) dit:

BTW: J'essayé d'installer un gestionnaire d'erreur via setErrorHandler, mais il n'y a toujours pas d'exception.

Ma question:

Ce qui a changé à 1,6 qui empêche la validation de schéma pour lancer une SAXParseException? Est-ce lié au schéma ou au xml que j'ai essayé d'analyser?

Mise à jour:

Le code suivant fonctionne sur 1,5 et 1,6 comme je l'ai été désirais:

@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))); 
    } 

La solution semble être d'utiliser explicitement une instance de validateur créée à partir de l'instance de schéma . J'ai trouvé la solution here

Cependant, je ne sais pas pourquoi c'est ...

Répondre

1

Apparemment, un document non conforme au schéma que mérite une légère réprimande sur stderr du gestionnaire d'erreurs par défaut. Ma solution consistait à remplacer le gestionnaire d'erreurs par défaut par un gestionnaire plus strict:

// 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;     
    } 
});