【发布时间】:2016-01-03 10:08:22
【问题描述】:
我有一个无效的 XSD 文件,我正在尝试用 Java 解析它。当我尝试解析无效的XSD 时,我只收到一次SAXParseException。第二次和所有后续尝试都不会产生SAXParseException。我不希望Java有错误,但也无法理解行为,每次都期待SAXParseException。非常欢迎任何帮助或解释。
这里有一个Java源码:
package com.myxsd;
import java.io.File;
import java.io.IOException;
import javax.xml.XMLConstants;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
public class ParseXSD {
public static void main(String[] args) throws IOException {
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
String file = ParseXSD.class.getClassLoader().getResource("com/myxsd/myxsd.xsd").getFile();
try {
Schema schema = sf.newSchema(new File(file));
} catch (SAXException e) {
e.printStackTrace();
}
// sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
try {
// no exception is thrown during second attempt to get schema
Schema schema = sf.newSchema(new File(file));
Validator validator = schema.newValidator();
validator.setErrorHandler(new MyErrorHandler());
// sample.xml gets validated without any issues
validator.validate(new StreamSource(ParseXSD.class.getClassLoader().getResource("com/myxsd/sample.xml").getFile()));
} catch (SAXException e) {
e.printStackTrace();
}
}
private static class MyErrorHandler implements ErrorHandler {
private boolean isValid = true;
public boolean isValid() {
return this.isValid;
}
@Override
public void warning(SAXParseException exc) {
exc.printStackTrace();
}
@Override
public void error(SAXParseException exc) throws SAXParseException {
exc.printStackTrace();
this.isValid = false;
throw exc;
}
@Override
public void fatalError(SAXParseException exc) throws SAXParseException {
exc.printStackTrace();
this.isValid = false;
throw exc;
}
}
}
和无效的 myxsd.xsd 文件:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:n1="www.myns.com/XMLSchema">
<xs:import namespace="www.myns.com/XMLSchema" schemaLocation="xsd/notexistingfile.xsd"/>
<xs:element name="mytype" type="n1:mytype">
</xs:element>
</xs:schema>
取消注释创建new SchemaFactory 的行可以解决该问题,但我希望SchemaFactory 应该用作单例。
第二次尝试不仅没有抛出SAXParseException,而且可以进行验证,如果是下面的sample.xml文件则成功:
<?xml version="1.0" encoding="UTF-8"?>
<mytype></mytype>
运行程序时的输出如下:
org.xml.sax.SAXParseException; systemId: file:/C:/workspace/XSD_PARSING/bin/com/myxsd/myxsd.xsd; lineNumber: 7; columnNumber: 45; src-resolve: Cannot resolve the name 'n1:mytype' to a(n) 'type definition' component.
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source)
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.reportSchemaErr(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.reportSchemaError(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.getGlobalDecl(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDElementTraverser.traverseNamedElement(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDElementTraverser.traverseGlobal(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.traverseSchemas(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.parseSchema(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadSchema(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadGrammar(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadGrammar(Unknown Source)
at com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory.newSchema(Unknown Source)
at javax.xml.validation.SchemaFactory.newSchema(Unknown Source)
at javax.xml.validation.SchemaFactory.newSchema(Unknown Source)
at com.myxsd.ParseXSD.main(ParseXSD.java:22)
com.sun.org.apache.xerces.internal.jaxp.validation.SimpleXMLSchema 的实例包含以下功能列表:
"http://apache.org/xml/features/validation/schema/augment-psvi" true
"http://apache.org/xml/features/continue-after-fatal-error" false
"http://javax.xml.XMLConstants/feature/secure-processing" true
"http://apache.org/xml/features/honour-all-schemaLocations" false
"http://apache.org/xml/features/validate-annotations" false
"http://apache.org/xml/features/validation/schema-full-checking" true
"http://apache.org/xml/features/internal/tolerate-duplicates" false
"http://apache.org/xml/features/generate-synthetic-annotations" false
"http://apache.org/xml/features/namespace-growth" false
"http://www.oracle.com/feature/use-service-mechanism" false
"http://apache.org/xml/features/disallow-doctype-decl" false
【问题讨论】:
-
您能检查一下第二次调用返回的架构类型吗?
-
com.sun.org.apache.xerces.internal.jaxp.validation.SimpleXMLSchema 的实例由后续调用返回。
-
我在这两种情况下都遇到了错误。你在什么 JRE 上执行你的代码?您是否还在寻找一种忽略无效导入的方法,或者只是好奇为什么您没有收到异常?
-
我尝试在 Java 6 和 Java 8 中构建和运行这个示例,两者都在 Windows 上。我很好奇原因,但它也可能是问题的根源,因为我的测试通过了,即使它们应该失败。
-
@stepasite 我在 SE 6、7 和 8 上进行了测试。在所有 3 上都得到了两个 catch 语句。你确定你正确地阅读了你的输出吗?