2010-03-12 65 views
6

最近,我們已將項目切換到Java 1.6。在執行測試時,我發現使用1.6時拋出的SAXParseException不會被拋出使用1.5。使用JRE 1.5和JDK 1.6時DocumentBuilder.parse的差異

下面是我的測試代碼來演示問題。

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

} 

當使用JVM 1.5時,測試通過,1.6失敗,出現「Expected exception SAXParseException」。

DocumentBuilderFactory.setSchema(Schema)方法的Javadoc說:

當由 驗證發現錯誤,解析器負責 他們報告給用戶指定 的ErrorHandler(或者,如果錯誤處理程序 是沒有設置,忽略它們或拋出它們),就像解析器本身找到的其他錯誤 一樣。在其他 也就是說,如果用戶指定 設置ErrorHandler時,它必須接收 這些錯誤,如果沒有,他們必須 根據 實現特定的默認錯誤 處理規則處理。

DocumentBuilder.parse(InputSource)方法的Javadoc中說:

BTW:我試圖通過setErrorHandler設置錯誤處理程序,但仍有也不例外。

現在我的問題:

發生了什麼變化1.6,可防止架構驗證拋出的SAXParseException?它與架構還是我試圖解析的xml有關?

更新:

下面的代碼工作在1.5和1.6,因爲我一直希望:

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

的解決方案似乎是明確使用從Schema實例創建一個Validator實例。 我已經找到了解決辦法here

不過我不知道這是爲什麼......

回答

1

顯然,文檔不符合模式只符合一個優點,溫和的譴責從默認的錯誤處理程序標準錯誤。我的解決方案是用一個更嚴格的替換默認錯誤處理程序:

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