我遇到了Java中XSD验证库提供的错误消息文本的问题。就我而言,似乎Apache Xerces是在引擎盖下使用的。 我发现Java中的错误至少具有误导性。
我从Java得到的错误是:
cvc-complex-type.2.4.b:元素“root”的内容不完整。预计会有一个'{subnode1,subnode2}'。
但另一个XML编辑器XMLSpy 2004说:
'subnode1'后面的强制元素:subnode2,subnode3
这里的第二个错误似乎更准确,因为没有丢失子节点1。但是,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>
这是我的Java代码,它调用验证API。
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));
}
}
我在这里遗漏了什么吗? 您是否知道可能更准确地计算错误消息的其他实现? 任何输入都表示赞赏。 谢谢!
答案 0 :(得分:1)
严格地说,您所谓的XMLSpy 2004给您的信息具有误导性。鉴于subnode1上的“无界”maxOccurs,人们无法确切地说出在最后一次遇到的subnode1之后会出现什么:是否应该有另一个或更多的subnode1,然后是子节点2和3?
唯一可以肯定的是,在出现错误时,subnode1或subnode2之一可能会跟随。
这正是你得到的另一条消息(你说的是Xerces,它与标准的.NET相匹配)告诉你......
想象一下,有人使用此信息构建一个编辑器,通过构建有效XML所需的步骤(例如,智能感知或图形编辑器中的某些上下文菜单)驱动用户。您认为哪一个更好地指导用户?我会将Xerces消息称为正确的消息,因为一旦我填写了一个subnode1,XML Spy 2004消息将继续建议只有一个节点2和3(如果我没有填写2,为什么3? ?如果我想继续添加subnode1,该怎么办?)
我的观点是,它取决于您对这些消息的期望。我个人认为,对于我所描述的任务类型,Xerces(以及所示的.NET也是正确的)消息是正确的。有些人可能会发现它过于迭代,即只有在你击中子节点后才会被告知“准备”一个子节点...我的问题,我猜......
但是想象一下另一个场景,你所展示的整个节点集都包含在一个可选的序列中,然后该序列后面跟着一个强制的子节点....然后,在你的情况下,该消息应该是{ {1}}。然后,如果上面提到的可选序列重复,该怎么办?
最后,考虑到XSD模型的本质,人们可以实现这种“向前看”,为您提供可能性......事实上,选项很容易复合到信息变得无用的地步......而下一步是什么?现在总是一件好事。