最近,我們已將項目切換到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
不過我不知道這是爲什麼......