根據 XSD 文件驗證 XML 文件
一、概述
在本教程中,我們將演示如何根據 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 文件,並且我們還可以列出所有驗證錯誤。
與往常一樣,代碼可在 GitHub 上獲得。