XSD 验证中的 SaxParseException 未给出元素名称
我有一个 xsd 文件和一个 xml 文件,我使用以下代码根据 xsd 文件验证 xml 文件
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(true);
factory.setAttribute(
"http://java.sun.com/xml/jaxp/properties/schemaLanguage",
"http://www.w3.org/2001/XMLSchema");
factory.setAttribute(
"http://java.sun.com/xml/jaxp/properties/schemaSource",
new InputSource(new StringReader(xsd)));
Document doc = null;
try {
DocumentBuilder parser = factory.newDocumentBuilder();
MyErrorHandler errorHandler = new MyErrorHandler();
parser.setErrorHandler(errorHandler);
doc = parser.parse(new InputSource(new StringReader(xml)));
return true;
} catch (ParserConfigurationException e) {
System.out.println("Parser not configured: " + e.getMessage());
} catch (SAXException e) {
System.out.print("Parsing XML failed due to a "
+ e.getClass().getName() + ":");
System.out.println(e.getMessage());
} catch (IOException e) {
System.out.println("IOException thrown");
e.printStackTrace();
}
return false;
MyErrorHanlder 是
private static class MyErrorHandler implements ErrorHandler {
public void warning(SAXParseException spe) throws SAXException {
System.out.println("Warning: " + spe.getMessage() + " getColumnNumber is " + spe.getColumnNumber() + " getLineNumber " + spe.getLineNumber() + " getPublicId " + spe.getPublicId() + " getSystemId " + spe.getSystemId());
}
public void error(SAXParseException spe) throws SAXException {
System.out.println("Error: " + spe.getMessage() + " getColumnNumber is " + spe.getColumnNumber() + " getLineNumber " + spe.getLineNumber() + " getPublicId " + spe.getPublicId() + " getSystemId " + spe.getSystemId());
throw new SAXException("Error: " + spe.getMessage());
}
public void fatalError(SAXParseException spe) throws SAXException {
System.out.println("Fatal Error: " + spe.getMessage() + " getColumnNumber is " + spe.getColumnNumber() + " getLineNumber " + spe.getLineNumber() + " getPublicId " + spe.getPublicId() + " getSystemId " + spe.getSystemId());
throw new SAXException("Fatal Error: " + spe.getMessage());
}
}
当 xml 不符合 xsd 时,我会得到一个异常..但此异常没有名称发生此错误的 xsd 元素。该消息看起来像
Parsing XML failed due to a org.xml.sax.SAXException:Error: cvc-minLength-valid: Value长度 = '0' 的 '' 相对于类型 'null' 的 minLength '1' 而言不是刻面有效的。
错误消息没有打印 xsd 元素的名称,而是只有 ''。因此,我无法找到并向用户显示导致错误的确切元素。
我的 xsd 元素看起来像这样
<xs:element name="FullName_FirstName">
<xs:annotation>
<xs:appinfo>
<ie:label>First Name</ie:label>
<ie:html_element>0</ie:html_element>
</xs:appinfo>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="1"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
提前致谢
I have an xsd file and an xml file, I am validating the xml file against the xsd file using the following code
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(true);
factory.setAttribute(
"http://java.sun.com/xml/jaxp/properties/schemaLanguage",
"http://www.w3.org/2001/XMLSchema");
factory.setAttribute(
"http://java.sun.com/xml/jaxp/properties/schemaSource",
new InputSource(new StringReader(xsd)));
Document doc = null;
try {
DocumentBuilder parser = factory.newDocumentBuilder();
MyErrorHandler errorHandler = new MyErrorHandler();
parser.setErrorHandler(errorHandler);
doc = parser.parse(new InputSource(new StringReader(xml)));
return true;
} catch (ParserConfigurationException e) {
System.out.println("Parser not configured: " + e.getMessage());
} catch (SAXException e) {
System.out.print("Parsing XML failed due to a "
+ e.getClass().getName() + ":");
System.out.println(e.getMessage());
} catch (IOException e) {
System.out.println("IOException thrown");
e.printStackTrace();
}
return false;
MyErrorHanlder is
private static class MyErrorHandler implements ErrorHandler {
public void warning(SAXParseException spe) throws SAXException {
System.out.println("Warning: " + spe.getMessage() + " getColumnNumber is " + spe.getColumnNumber() + " getLineNumber " + spe.getLineNumber() + " getPublicId " + spe.getPublicId() + " getSystemId " + spe.getSystemId());
}
public void error(SAXParseException spe) throws SAXException {
System.out.println("Error: " + spe.getMessage() + " getColumnNumber is " + spe.getColumnNumber() + " getLineNumber " + spe.getLineNumber() + " getPublicId " + spe.getPublicId() + " getSystemId " + spe.getSystemId());
throw new SAXException("Error: " + spe.getMessage());
}
public void fatalError(SAXParseException spe) throws SAXException {
System.out.println("Fatal Error: " + spe.getMessage() + " getColumnNumber is " + spe.getColumnNumber() + " getLineNumber " + spe.getLineNumber() + " getPublicId " + spe.getPublicId() + " getSystemId " + spe.getSystemId());
throw new SAXException("Fatal Error: " + spe.getMessage());
}
}
And when the xml does not comply with xsd I get an exception.. but this exception does not have the name of the xsd element due to which this error has occured .. The message looks like
Parsing XML failed due to a org.xml.sax.SAXException:Error: cvc-minLength-valid: Value '' with length = '0' is not facet-valid with respect to minLength '1' for type 'null'.
Instead of printing the name of the xsd element, the error message just has ''. Because of this I am not able to find and display(to the user) the exact element which is causing the error.
My xsd element looks like this
<xs:element name="FullName_FirstName">
<xs:annotation>
<xs:appinfo>
<ie:label>First Name</ie:label>
<ie:html_element>0</ie:html_element>
</xs:appinfo>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="1"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
Thanks in advance
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
首先,一些建议。您不需要仅仅为了进行验证而构建 DOM 文档。这会导致大量内存开销,甚至可能会耗尽大型输入 XML 文档。您可以只使用
SAXParser
。如果您使用的是 Java 1.5 或更高版本,则甚至没有必要。从该版本开始,Java SE 中包含了 XML 验证 API。检查包 javax.xml.validation 了解更多信息。这个想法是,您首先构建一个Schema
对象,然后从中获取一个可用于验证的Validator
。它接受任何Source
实现作为输入。验证器也可以被赋予ErrorHandlers,这样你就可以重用你的类。当然,您可能实际上需要一个 DOM,但在这种情况下,最好创建一个Schema
实例并将其注册到您的DocumentBuilderFactory
中。现在,针对实际问题。这并不完全容易,因为
SAXParseException
没有为您提供太多上下文信息。最好的办法是在某处连接一个ContentHandler
并跟踪您所在的元素,或一些其他位置信息。然后,您可以在需要时将其提供给错误处理程序。DefaultHandler
或DefaultHandler2
类是结合错误和内容处理的便捷方法。您将在包 org.xml.sax.ext 中找到这些类。我整理了一个测试,将在下面发布。现在,我确实得到了两行输出,而不是预期的输出。如果这是因为我正在使用架构,或者因为我没有抛出异常并继续处理,我不确定。第二行确实包含元素的名称,因此这可能就足够了。您可以在错误上设置一些标志,而不是抛出异常并结束解析。
这有点粗糙,但您可以从此基础上努力以获得您需要的东西。
First of all, some advice. You don't need to build a DOM document just to do validation. This causes a large amount of memory overhead, maybe even running out on large input XML documents. You could just use a
SAXParser
. If you're using Java 1.5 or later, that isn't even necessary. From that version on, an XML validation API was included in Java SE. Check package javax.xml.validation for more info. The idea is that you first build aSchema
object, then obtain aValidator
from that which can be used to do validation. It accepts anySource
implementation for input. Validators can also be givenErrorHandlers
, so you can just reuse your class. Of course, it is possible that you actually will need a DOM, but in that case it's still better to make aSchema
instance and register that with yourDocumentBuilderFactory
.Now, for the actual problem. This isn't entirely easy, since the
SAXParseException
doesn't provide you with much context information. Your best bet is to have aContentHandler
hooked up somewhere and keep track of what element you're in, or some other positional information. You could then have that given to the error handler when needed. The classDefaultHandler
orDefaultHandler2
is a convenient way of combining both error and content handling. You'll find those classes in package org.xml.sax.ext.I've put together a test that I'll post below. Now, I do get two lines of output instead of the expected one. If this is because I'm using a Schema, or because I'm not throwing an exception and keep on processing, I'm not certain. The second line does contain the name of the element, so that might be enough. You could have some flag set on errors instead of throwing an exception and ending the parsing.
It's a bit rough, but you can work on from this to get what you need.