拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 根据XSD 文件验证XML 文件

根据XSD 文件验证XML 文件

白鹭 - 2022-07-21 2129 0 2

一、概述

在本教程中,我们将演示如何根据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 文件对应的SchemaSchema表示一组约束。

最后,我们将从Schema中检索ValidatorValidator是根据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.xmlperson.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 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *