一、概述
在本教程中,我们将演示如何根据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 评论