最近,我们终于将我们的项目切换到了 Java 1.6。执行测试时,我发现使用 1.6 不会引发使用 1.5 引发的 SAXParseException。
下面是我的测试代码来演示这个问题。
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 上它失败并出现“预期异常 SAXParseException”。
DocumentBuilderFactory.setSchema(Schema)方法的 Javadoc说:
当验证器发现错误时,解析器负责将它们报告给用户指定的 ErrorHandler(或者如果未设置错误处理程序,则忽略它们或抛出它们),就像解析器本身发现的任何其他错误一样。换句话说,如果设置了用户指定的 ErrorHandler,它必须接收这些错误,如果没有,则必须根据实现特定的默认错误处理规则来处理它们。
DocumentBuilder.parse(InputSource)方法的 Javadoc说:
顺便说一句:我尝试通过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 实例。我在这里找到了解决方案
我仍然不确定这是为什么...