一、概述
在本教程中,我们将演示如何根据XSD 文件验证XML 文件。
2.定义一个XML和两个XSD文件
让我们考虑以下XML 文件baeldung.xml,其中包含名称和地址,本身由邮政编码和城市构成:
<?xml version="1.0" encoding="UTF-8" ?> <individual> <name>Baeldung</name> <address> <zip>00001</zip> <city>New York</city> </address> </individual>
baeldung.xml 的内容与baeldung.xml文件的描述完全person.xsd:
<?xml version="1.0" encoding="UTF-8" ?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="individual"> <xs:complexType> <xs:sequence> <xs:element name="name" type="xs:string" /> <xs:element name="address"> <xs:complexType> <xs:sequence> <xs:element name="zip" type="xs:positiveInteger" /> <xs:element name="city" type="xs:string" /> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>
但是,我们的XML 对于以下XSD 文件full-person.xsd:
<?xml version="1.0" encoding="UTF-8" ?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="individual"> <xs:complexType> <xs:sequence> <xs:element name="name"> <xs:simpleType> <xs:restriction base="xs:string"> <xs:maxLength value="5" /> </xs:restriction> </xs:simpleType> </xs:element> <xs:element name="address"> <xs:complexType> <xs:sequence> <xs:element name="zip" type="xs:positiveInteger" /> <xs:element name="city" type="xs:string" /> <xs:element name="street" type="xs:string" /> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>
有两个问题:
名称属性限制为最多5 个字符
地址需要街道属性
让我们看看如何使用Java 来获取这些信息。
3. 根据XSD 文件验证XML 文件
**javax.xml.validation包定义了一个用于验证XML 文档的API。
**
首先,我们将准备一个能够读取遵循XML Schema 1.0 规范的文件的SchemaFactory。然后,我们将使用这个SchemaFactory来创建与我们的XSD 文件对应的Schema。Schema表示一组约束。
最后,我们将从Schema中检索Validator。Validator是根据Schema检查XML 文档的处理器:
private Validator initValidator(String xsdPath) throws SAXException {
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Source schemaFile = new StreamSource(getFile(xsdPath));
Schema schema = factory.newSchema(schemaFile);
return schema.newValidator();
}在此代码中,getFile方法允许我们将XSD 读入File。在我们的示例中,我们将文件放在资源目录下,因此该方法为:
private File getFile(String location) {
return new File(getClass().getClassLoader().getResource(location).getFile());
}请注意,当我们创建Schema时,如果XSD 文件无效,则可能会引发SAXException。
我们现在可以使用Validator来验证XML 文件是否与XSD 描述匹配。 validate方法要求我们将File转换为StreamSource:
public boolean isValid(String xsdPath, String xmlPath) throws IOException, SAXException {
Validator validator = initValidator(xsdPath);
try {
validator.validate(new StreamSource(getFile(xmlPath)));
return true;
} catch (SAXException e) {
return false;
}
}如果在解析过程中出现错误,则validate方法会引发SAXException。这表明XML 文件在给定XSD 规范的情况下无效。
如果在读取文件时存在潜在问题,validate方法也可以抛出[IOException](https://baeldung-cn.com/java-checked-unchecked-exceptions)。
我们现在可以将代码包装在XmlValidator类中,并检查baeldung.xml与person.xsd描述匹配,但与full-person.xsd不匹配:
@Test
public void givenValidXML_WhenIsValid_ThenTrue() throws IOException, SAXException {
assertTrue(new XmlValidator().isValid("person.xsd", "baeldung.xml"));
}
@Test
public void givenInvalidXML_WhenIsValid_ThenFalse() throws IOException, SAXException {
assertFalse(new XmlValidator().isValid("full-person.xsd", "baeldung.xml"));
}4. 列出所有验证错误
validate方法的基本行为是在解析抛出SAXException时退出。
现在我们想要收集所有验证错误,我们需要改变这种行为。为此,我们必须定义自己的ErrorHandler:
public class XmlErrorHandler implements ErrorHandler {
private List<SAXParseException> exceptions;
public XmlErrorHandler() {
this.exceptions = new ArrayList<>();
}
public List<SAXParseException> getExceptions() {
return exceptions;
}
@Override
public void warning(SAXParseException exception) {
exceptions.add(exception);
}
@Override
public void error(SAXParseException exception) {
exceptions.add(exception);
}
@Override
public void fatalError(SAXParseException exception) {
exceptions.add(exception);
}
}我们现在可以告诉Validator使用这个特定的ErrorHandler:
public List<SAXParseException> listParsingExceptions(String xsdPath, String xmlPath) throws IOException, SAXException {
XmlErrorHandler xsdErrorHandler = new XmlErrorHandler();
Validator validator = initValidator(xsdPath);
validator.setErrorHandler(xsdErrorHandler);
try {
validator.validate(new StreamSource(getFile(xmlPath)));
} catch (SAXParseException e)
{
// ...
}
xsdErrorHandler.getExceptions().forEach(e -> LOGGER.info(e.getMessage()));
return xsdErrorHandler.getExceptions();
}由于baeldung.xml符合person.xsd的要求,因此在这种情况下没有列出错误。但是,使用full-person.xsd调用,我们将打印以下错误消息:
XmlValidator - cvc-maxLength-valid: Value 'Baeldung' with length = '8' is not facet-valid with respect to maxLength '5' for type '#AnonType_nameindividual'.
XmlValidator - cvc-type.3.1.3: The value 'Baeldung' of element 'name' is not valid.
XmlValidator - cvc-complex-type.2.4.b: The content of element 'address' is not complete. One of '{street}' is expected.我们在第1 节中提到的所有错误都是由程序发现的。
5. 结论
在本文中,我们了解了如何根据XSD 文件验证XML 文件,并且我们还可以列出所有验证错误。
0 评论