2010-03-12 77 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;     
    } 
});