1. 개요

이 사용방법(예제)에서는 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 의 내용은 정확히 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>

그러나 다음 XSD 파일 full-person.xsd 와 관련하여 XML이 유효하지 않습니다 .

<?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 스키마 1.0 사양을 따르는 파일을 읽을 수 있는 SchemaFactory 를 준비합니다. 그런 다음 이 SchemaFactory 를 사용하여 XSD 파일에 해당하는 스키마 를 생성 합니다. 스키마제약 조건 집합을 나타냅니다.

마지막으로 Schema 에서 Validator 를 검색합니다 . 유효성 검사기 는 스키마대해 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 메서드를 사용 하면 XSDFile 로 읽을 수 있습니다 . 이 예제에서는 파일을 리소스 디렉터리 아래에 두므로 이 메서드는 다음과 같이 읽습니다.

private File getFile(String location) {
    return new File(getClass().getClassLoader().getResource(location).getFile());
}

Schema만들 때 XSD 파일이 유효하지 않으면 SAXException 이 발생할 수 있습니다.

이제 유효성 검사기 를 사용하여 XML 파일이 XSD 설명과 일치하는지 확인할 수 있습니다. 유효성 검증 메소드를 사용하려면 파일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;
    }
}

유효성 검사 메서드 는 구문 분석 중에 오류가 있는 경우 SAXException  을 throw합니다 . 이는 XML 파일이 주어진 XSD 사양에서 유효하지 않음을 나타냅니다.

유효성 검사 메서드 는 파일을 읽는 동안 근본적인 문제가 있는 경우 IOException 을 throw할 수도 있습니다 .

이제 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. 모든 유효성 검사 오류 나열

유효성 검사 메서드 의 기본 동작은 구문 분석에서 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에서 사용할 수 있습니다 .

Generic footer banner