XSD 파일에 대해 XML 파일의 유효성을 검사하는 가장 좋은 방법은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/15732

  •  08-06-2019
  •  | 
  •  

문제

나에게 주어진 xsd 파일을 준수해야 하는 일부 XML 파일을 생성 중입니다.준수 여부를 확인하는 가장 좋은 방법은 무엇입니까?

도움이 되었습니까?

해결책

Java 런타임 라이브러리는 유효성 검사를 지원합니다.마지막으로 이것을 확인했을 때 덮개 아래에 있는 Apache Xerces 파서가 있었습니다.아마도 javax.xml.validation.Validator.

import javax.xml.XMLConstants;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.*;
import java.net.URL;
import org.xml.sax.SAXException;
//import java.io.File; // if you use File
import java.io.IOException;
...
URL schemaFile = new URL("http://host:port/filename.xsd");
// webapp example xsd: 
// URL schemaFile = new URL("http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd");
// local file example:
// File schemaFile = new File("/location/to/localfile.xsd"); // etc.
Source xmlFile = new StreamSource(new File("web.xml"));
SchemaFactory schemaFactory = SchemaFactory
    .newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
try {
  Schema schema = schemaFactory.newSchema(schemaFile);
  Validator validator = schema.newValidator();
  validator.validate(xmlFile);
  System.out.println(xmlFile.getSystemId() + " is valid");
} catch (SAXException e) {
  System.out.println(xmlFile.getSystemId() + " is NOT valid reason:" + e);
} catch (IOException e) {}

스키마 팩토리 상수는 문자열입니다. http://www.w3.org/2001/XMLSchema XSD를 정의합니다.위 코드는 URL에 대해 WAR 배포 설명자의 유효성을 검사합니다. http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd 하지만 로컬 파일에 대해서도 쉽게 유효성을 검사할 수 있습니다.

문서의 유효성을 검사하기 위해 DOMParser를 사용해서는 안 됩니다(어쨌든 문서 개체 모델을 만드는 것이 목표가 아닌 이상).그러면 문서를 구문 분석하면서 DOM 개체가 생성되기 시작합니다. 이를 사용하지 않으면 낭비입니다.

다른 팁

이를 사용하여 수행하는 방법은 다음과 같습니다. Xerces2.이에 대한 튜토리얼, 여기 (요구.가입하기).

원래 속성:노골적으로 복사한 것 여기:

import org.apache.xerces.parsers.DOMParser;
import java.io.File;
import org.w3c.dom.Document;

public class SchemaTest {
  public static void main (String args[]) {
      File docFile = new File("memory.xml");
      try {
        DOMParser parser = new DOMParser();
        parser.setFeature("http://xml.org/sax/features/validation", true);
        parser.setProperty(
             "http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation", 
             "memory.xsd");
        ErrorChecker errors = new ErrorChecker();
        parser.setErrorHandler(errors);
        parser.parse("memory.xml");
     } catch (Exception e) {
        System.out.print("Problem parsing the file.");
     }
  }
}

ant를 사용하여 프로젝트를 빌드하므로 스키마 유효성 검사 작업을 사용하여 구성 파일을 확인할 수 있습니다.

<schemavalidate> 
    <fileset dir="${configdir}" includes="**/*.xml" />
</schemavalidate>

이제 잘못된 구성 파일은 빌드에 실패합니다!

http://ant.apache.org/manual/Tasks/schemavalidate.html

이것은 인기 있는 질문이므로 Java가 "참조된" xsd에 대해서도 유효성을 검사할 수 있다는 점을 지적하겠습니다. 예를 들어 .xml 파일 자체가 헤더에 XSD를 지정하는 경우 다음을 사용합니다. xsi:SchemaLocation 또는 xsi:noNamespaceSchemaLocation (또는 특정 네임스페이스의 경우 xsi) 전- :

<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:noNamespaceSchemaLocation="http://www.example.com/document.xsd">
  ...

또는 SchemaLocation(항상 xsd 매핑에 대한 네임스페이스 목록)

<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:SchemaLocation="http://www.example.com/my_namespace http://www.example.com/document.xsd">
  ...

.xsd 파일은 .xml 파일에 선언된 네임스페이스에 "매핑"하고, 네임스페이스를 선언하고, .xml 파일의 네임스페이스와 일치하면 괜찮기 때문에 다른 답변도 여기에서 작동합니다.하지만 때로는 맞춤 설정을 하는 것이 편리할 때도 있습니다. 리졸버...

javadocs에서:"URL, 파일 또는 소스를 지정하지 않고 스키마를 생성하면 Java 언어는 검증 중인 문서에서 사용해야 하는 스키마를 찾는 스키마를 생성합니다.예를 들어:"

SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
Schema schema = factory.newSchema();

이는 여러 네임스페이스 등에 대해 작동합니다.이 접근법의 문제점은 xmlsns:xsi 아마도 네트워크 위치일 것이므로 기본적으로 모든 검증을 통해 네트워크에 나가서 항상 최적이지는 않습니다.

다음은 XML 파일이 참조하는 XSD와 비교하여 XML 파일의 유효성을 검사하는 예입니다(네트워크에서 가져와야 하는 경우에도 마찬가지).

  public static void verifyValidatesInternalXsd(String filename) throws Exception {
    InputStream xmlStream = new new FileInputStream(filename);
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    factory.setValidating(true);
    factory.setNamespaceAware(true);
    factory.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaLanguage",
                 "http://www.w3.org/2001/XMLSchema");
    DocumentBuilder builder = factory.newDocumentBuilder();
    builder.setErrorHandler(new RaiseOnErrorHandler());
    builder.parse(new InputSource(xmlStream));
    xmlStream.close();
  }

  public static class RaiseOnErrorHandler implements ErrorHandler {
    public void warning(SAXParseException e) throws SAXException {
      throw new RuntimeException(e);
    }
    public void error(SAXParseException e) throws SAXException {
      throw new RuntimeException(e);
    }
    public void fatalError(SAXParseException e) throws SAXException {
      throw new RuntimeException(e);
    }
  }

xml 파일이 URL을 참조하더라도 xsd를 수동으로 지정하거나(여기서 다른 답변 참조) "XML 카탈로그"를 사용하여 네트워크에서 참조된 XSD를 가져오는 것을 피할 수 있습니다. 스타일 리졸버.봄도 마찬가지인 것 같다 가로챌 수 있다 유효성 검사를 위해 로컬 파일을 제공하기 위한 URL 요청입니다.또는 다음을 통해 직접 설정할 수도 있습니다. setResourceResolver, 전:

Source xmlFile = new StreamSource(xmlFileLocation);
SchemaFactory schemaFactory = SchemaFactory
                                .newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = schemaFactory.newSchema();
Validator validator = schema.newValidator();
validator.setResourceResolver(new LSResourceResolver() {
  @Override
  public LSInput resolveResource(String type, String namespaceURI,
                                 String publicId, String systemId, String baseURI) {
    InputSource is = new InputSource(
                           getClass().getResourceAsStream(
                          "some_local_file_in_the_jar.xsd"));
                          // or lookup by URI, etc...
    return new Input(is); // for class Input see 
                          // https://stackoverflow.com/a/2342859/32453
  }
});
validator.validate(xmlFile);

또한보십시오 여기 다른 튜토리얼을 위해.

기본값은 DOM 구문 분석을 사용하는 것이라고 생각합니다. 유효성을 검사하는 SAX 파서와 비슷한 작업을 수행할 수 있습니다. 또한 saxReader.setEntityResolver(your_resolver_here);

Java 7을 사용하면 다음 문서에 제공된 문서를 따를 수 있습니다. 패키지 설명.

// parse an XML document into a DOM tree
DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document document = parser.parse(new File("instance.xml"));

// create a SchemaFactory capable of understanding WXS schemas
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);

// load a WXS schema, represented by a Schema instance
Source schemaFile = new StreamSource(new File("mySchema.xsd"));
Schema schema = factory.newSchema(schemaFile);

// create a Validator instance, which can be used to validate an instance document
Validator validator = schema.newValidator();

// validate the DOM tree
try {
    validator.validate(new DOMSource(document));
} catch (SAXException e) {
    // instance document is invalid!
}

Linux-Machine이 있는 경우 무료 명령줄 도구 SAXCount를 사용할 수 있습니다.나는 이것이 매우 유용하다고 생각했습니다.

SAXCount -f -s -n my.xml

dtd 및 xsd에 대해 유효성을 검사합니다.50MB 파일의 경우 5초.

데비안 스퀴즈에서는 "libxerces-c-samples" 패키지에 있습니다.

dtd와 xsd의 정의는 xml에 있어야 합니다!별도로 구성할 수는 없습니다.

답변 하나 더:당신이 파일의 유효성을 검사해야 한다고 말했으니까 생성 (쓰기) 먼저 쓴 다음 검증을 위해 다시 읽는 대신, 쓰는 동안 콘텐츠의 유효성을 검사할 수 있습니다.SAX 기반 작성자를 사용하는 경우 Xml 유효성 검사를 위해 JDK API를 사용하여 이를 수행할 수 있습니다.그렇다면 'Validator.validate(source, result)'를 호출하여 유효성 검사기에 링크하면 됩니다. 소스는 작성자에서 가져오고 결과는 출력이 필요한 곳입니다.

또는 콘텐츠 작성을 위해 Stax(또는 stax를 사용하거나 사용할 수 있는 라이브러리)를 사용하는 경우 우드스톡스 XMLStreamWriter를 사용할 때 유효성 검사를 직접 지원할 수도 있습니다.여기 블로그 항목 그 방법을 보여줍니다:

프로그래밍 방식으로 XML 파일을 생성하는 경우 다음을 살펴보는 것이 좋습니다. XMLBeans 도서관.XMLBeans는 명령줄 도구를 사용하여 XSD를 기반으로 Java 객체 세트를 자동으로 생성하고 패키지화합니다.그런 다음 이러한 개체를 사용하여 이 스키마를 기반으로 하는 XML 문서를 작성할 수 있습니다.

스키마 유효성 검사에 대한 지원이 내장되어 있으며 Java 개체를 XML 문서로 또는 그 반대로 변환할 수 있습니다.

비버 그리고 JAXB XMLBeans와 유사한 목적을 제공하는 다른 Java 라이브러리입니다.

도구나 라이브러리를 찾고 계십니까?

라이브러리에 관한 한 사실상의 표준은 다음과 같습니다. Xerces2 둘 다 가지고 있는 것 C++ 그리고 자바 버전.

그러나 이는 무거운 솔루션이라는 점을 미리 경고하십시오.그러나 XSD 파일에 대해 XML의 유효성을 검사하는 것은 다소 무거운 문제입니다.

이 작업을 수행하는 도구는 다음과 같습니다. XML폭스 괜찮은 프리웨어 솔루션인 것 같지만 개인적으로 사용해본 적이 없어서 확실하게 말할 수는 없습니다.

JAXB를 사용하면 아래 코드를 사용할 수 있습니다.

    @Test
public void testCheckXmlIsValidAgainstSchema() {
    logger.info("Validating an XML file against the latest schema...");

    MyValidationEventCollector vec = new MyValidationEventCollector();

    validateXmlAgainstSchema(vec, inputXmlFileName, inputXmlSchemaName, inputXmlRootClass);

    assertThat(vec.getValidationErrors().isEmpty(), is(expectedValidationResult));
}

private void validateXmlAgainstSchema(final MyValidationEventCollector vec, final String xmlFileName, final String xsdSchemaName, final Class<?> rootClass) {
    try (InputStream xmlFileIs = Thread.currentThread().getContextClassLoader().getResourceAsStream(xmlFileName);) {
        final JAXBContext jContext = JAXBContext.newInstance(rootClass);
        // Unmarshal the data from InputStream
        final Unmarshaller unmarshaller = jContext.createUnmarshaller();

        final SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
        final InputStream schemaAsStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(xsdSchemaName);
        unmarshaller.setSchema(sf.newSchema(new StreamSource(schemaAsStream)));

        unmarshaller.setEventHandler(vec);

        unmarshaller.unmarshal(new StreamSource(xmlFileIs), rootClass).getValue(); // The Document class is the root object in the XML file you want to validate

        for (String validationError : vec.getValidationErrors()) {
            logger.trace(validationError);
        }
    } catch (final Exception e) {
        logger.error("The validation of the XML file " + xmlFileName + " failed: ", e);
    }
}

class MyValidationEventCollector implements ValidationEventHandler {
    private final List<String> validationErrors;

    public MyValidationEventCollector() {
        validationErrors = new ArrayList<>();
    }

    public List<String> getValidationErrors() {
        return Collections.unmodifiableList(validationErrors);
    }

    @Override
    public boolean handleEvent(final ValidationEvent event) {
        String pattern = "line {0}, column {1}, error message {2}";
        String errorMessage = MessageFormat.format(pattern, event.getLocator().getLineNumber(), event.getLocator().getColumnNumber(),
                event.getMessage());
        if (event.getSeverity() == ValidationEvent.FATAL_ERROR) {
            validationErrors.add(errorMessage);
        }
        return true; // you collect the validation errors in a List and handle them later
    }
}

온라인 스키마에 대해 검증

Source xmlFile = new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream("your.xml"));
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = factory.newSchema(Thread.currentThread().getContextClassLoader().getResource("your.xsd"));
Validator validator = schema.newValidator();
validator.validate(xmlFile);

로컬 스키마에 대해 유효성을 검사합니다.

Java를 사용한 오프라인 XML 유효성 검사

XSD에 대해 XML의 유효성을 한 번만 확인해야 했기 때문에 XMLFox를 사용해 보았습니다.나는 그것이 매우 혼란스럽고 이상하다는 것을 알았습니다.도움말 지침이 인터페이스와 일치하지 않는 것 같습니다.

저는 사용하기가 훨씬 쉽고 더 즉각적으로 친숙한 LiquidXML Studio 2008(v6)을 사용하게 되었습니다(UI는 제가 자주 사용하는 Visual Basic 2008 Express와 매우 유사합니다).단점:무료 버전에는 유효성 검사 기능이 없어서 30일 평가판을 사용해야 했습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top