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

나에게 주어진 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/XMLSchemaXSD를 정의 하는 문자열 입니다. 위의 코드는 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 태스크를 사용하여 구성 파일을 확인할 수 있습니다.

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

이제 나쁜 구성 파일이 빌드에 실패합니다!

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


답변

이것은 대중적인 질문이므로 java는 .xml 파일 자체가 헤더에 XSD를 지정 xsi:SchemaLocation하거나 xsi:noNamespaceSchemaLocation(또는 특정 네임 스페이스의 경우 xsi) ex :

<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은 네트워크 위치 일 가능성이 있기 때문에 기본적으로 항상 최적의 것은 아니지만 모든 유효성 검사를 수행하여 네트워크를 종료합니다.

다음은 참조하는 모든 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 catalog” 스타일 resolver 를 사용하여 네트워크에서 참조 된 XSD를 가져 오는 것을 피할 수 있습니다 . Spring은 분명히 유효성 검사를 위해 로컬 파일을 제공하기 위해 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을 사용하면 패키지 설명에 제공된 설명서를 따를 수 있습니다 .

// 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 StreamSource(new File("instance.xml"));
} 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를 사용하는 경우 Woodstox 는 XMLStreamWriter를 사용할 때 유효성 검사를 직접 지원할 수도 있습니다. 수행 방법을 보여주는 블로그 항목 은 다음과 같습니다 .