根據 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 上獲得。