我对 Java 中的 XSD 验证库提供的错误消息文本有疑问。就我而言,似乎在后台使用了 Apache Xerces。 我发现 Java 的错误至少具有误导性。
我从 Java 得到的错误是:
cvc-complex-type.2.4.b: The content of element 'root' is not complete. One of '{subnode1, subnode2}' is expected.
但另一个 XML 编辑器 XMLSpy 2004 是这样说的:
Mandatory elements expected in '' after 'subnode1': subnode2, subnode3
第二个错误在这里似乎更准确,因为没有 subnode1 丢失。而subnode2和subnode3都是。
这是我的 XML 文件:
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="schema.xsd">
<subnode0/>
<subnode1/>
</root>
这是我使用的 XSD:
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="root" type="NodeType">
</xs:element>
<xs:complexType name="NodeType">
<xs:sequence>
<xs:element name="subnode0" type="subnode0_Type" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="subnode1" type="subnode1_Type" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="subnode2" type="subnode2_Type" minOccurs="1" maxOccurs="1"/>
<xs:element name="subnode3" type="subnode3_Type" minOccurs="1" maxOccurs="1"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="subnode0_Type">
</xs:complexType>
<xs:complexType name="subnode1_Type">
</xs:complexType>
<xs:complexType name="subnode2_Type">
</xs:complexType>
<xs:complexType name="subnode3_Type">
</xs:complexType>
</xs:schema>
这是调用验证 API 的 Java 代码。
public class XsdErrorTextMain {
private final static DocumentBuilder documentBuilder;
private final static SchemaFactory schemaFactory;
static {
try {
final DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setNamespaceAware(true);
documentBuilder = documentBuilderFactory.newDocumentBuilder();
} catch (final ParserConfigurationException e) {
throw new RuntimeException(e);
}
schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
}
public static void main(final String[] args) throws Exception {
final Document xmlDocument = readXmlFile("file.xml");
final Schema schema = readXsdFile("schema.xsd");
runXmlValidation(xmlDocument, schema);
}
private static void runXmlValidation(final Document xmlDocument, final Schema schema) throws SAXException {
try {
final Validator validator = schema.newValidator();
validator.setErrorHandler(new ErrorHandler() {
@Override
public void warning(final SAXParseException exception) {
return;
}
@Override
public void error(final SAXParseException exception) throws SAXException {
displayValidationError(exception);
}
@Override
public void fatalError(final SAXParseException exception) throws SAXException {
throw new RuntimeException("A fatal error was raised during the validation", exception);
}
});
validator.validate(new DOMSource(xmlDocument));
} catch (final IOException e) {
throw new RuntimeException(e);
}
}
private static void displayValidationError(final SAXParseException validationError) {
System.out.println("Line: " + validationError.getLineNumber());
System.out.println("Column: " + validationError.getColumnNumber());
System.out.println("Message: " + validationError.getMessage());
}
private static Document readXmlFile(final String path) throws IOException, SAXException {
try (final InputStream xmlInputStream = ClassLoader.getSystemResource(path).openStream()) {
return documentBuilder.parse(xmlInputStream);
}
}
private static Schema readXsdFile(final String path) throws IOException, SAXException {
final Document xsdDocument = readXmlFile(path);
return schemaFactory.newSchema(new DOMSource(xsdDocument));
}
}
我是不是漏掉了什么? 您是否知道可以更准确地计算错误消息的其他实现? 任何输入表示赞赏。 谢谢!
最佳答案
严格来说,您所称的 XMLSpy 2004 给您的消息具有误导性。给定子节点 1 上的“无限”maxOccurs,人们不能真正肯定地说出最后一次遇到子节点 1 之后应该发生什么:是否应该有另一个或更多子节点 1,然后是子节点 2 和 3?
唯一可以肯定的是 subnode1 或 subnode2 中的一个可能会跟随在出现错误的位置。
这正是您收到的其他消息(您说的 Xerces,顺便说一句,它与标准 .NET 的消息相匹配)告诉您的...
想象一下,有人使用这些信息来构建一个编辑器,驱动用户完成构建有效 XML 所需的步骤(例如 Intellisense,或图形编辑器中的某些上下文菜单)。你认为哪一个更能引导用户?我认为 Xerces 消息是正确的,因为一旦我填写了一个子节点 1,XML Spy 2004 消息将继续建议节点 2 和 3(如果我没有填写 2,为什么是 3 ? 如果我想继续添加 subnode1 怎么办?)
我的意思是,这取决于您对这些消息的期望。不过,我个人认为 Xerces(如前所述,还有 .NET)消息对于我所描述的任务类型来说是正确的。有些人可能会觉得它太重复了,也就是说,只有在你点击了一个子节点 2 之后,你才会被告知“准备”一个子节点 3……你的问题,我猜……
但是想象另一种情况,您显示的整组节点都包含在一个可选序列中,并且该序列后跟一个强制性子节点 4...。那么在您的情况下,消息应该是 '' after 'subnode1': subnode2, subnode3, subnode4
.然后,如果我上面提到的可选序列重复出现怎么办?
最后,考虑到 XSD 模型的性质,可以实现这种“前瞻性”来为您提供可能性……问题是,选项很容易复合到信息变得无用的程度……而下一步是什么对现在来说总是一件好事。
关于java - Java 中误导性的 XSD 验证错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19444998/