XML ファイルを XSD ファイルと比較して検証する最良の方法は何ですか?

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 オブジェクトの作成が開始されますが、使用しない場合は無駄です。

他のヒント

これを使用してそれを行う方法は次のとおりです ゼルセス2. 。このためのチュートリアル、 ここ (必須サインアップ)。

元の帰属:~から露骨にコピーされた ここ:

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 は「参照された」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 ファイル内の名前空間と一致する場合は問題ありません。しかし、カスタムできると便利な場合もあります。 リゾルバ...

Javadoc から:「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 マシンをお持ちの場合は、無料のコマンドライン ツール SAXCount を使用できます。これはとても便利だと思いました。

SAXCount -f -s -n my.xml

dtd および xsd に対して検証されます。50MBのファイルの場合は5秒。

Debian Squeeze では、「libxerces-c-samples」パッケージにあります。

dtd と xsd の定義は XML 内に存在する必要があります。それらを個別に構成することはできません。

もう一つの答え:ファイルを検証する必要があると言ったので、 生成する (書き込み) 場合は、最初に書いてから検証のために読み戻すのではなく、書き込み中にコンテンツを検証したい場合があります。SAX ベースのライターを使用している場合は、Xml 検証用の JDK API を使用してこれを実行できる可能性があります。その場合は、「Validator.validate(source, result)」を呼び出してバリデーターにリンクするだけです。ソースはライターから取得され、result は出力が必要な場所になります。

あるいは、コンテンツの作成に Stax を使用する場合 (または、Stax を使用する、または使用できるライブラリ)、 ウッドストックス XMLStreamWriter を使用する場合、検証を直接サポートすることもできます。ここにあります ブログの記事 それがどのように行われるかを示します:

XML ファイルをプログラムで生成している場合は、 XMLBeans 図書館。XMLBeans は、コマンド ライン ツールを使用して、XSD に基づいて Java オブジェクトのセットを自動的に生成し、パッケージ化します。これらのオブジェクトを使用して、このスキーマに基づいて XML ドキュメントを構築できます。

スキーマ検証のサポートが組み込まれており、Java オブジェクトを XML ドキュメントに変換したり、その逆に変換したりできます。

キャスター そして JAXB は、XMLBean と同様の目的を果たす他の Java ライブラリです。

ツールまたはライブラリをお探しですか?

ライブラリに関する限り、ほぼデファクトスタンダードは次のとおりです。 ゼルセス2 両方を持っているのは 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 検証

XML を XSD に対して 1 回だけ検証する必要があったので、XMLFox を試してみました。とても混乱していて奇妙だと思いました。ヘルプの説明がインターフェイスと一致していないようでした。

私は最終的に LiquidXML Studio 2008 (v6) を使用しました。これははるかに使いやすく、すぐに馴染みました (UI は私が頻繁に使用する Visual Basic 2008 Express に非常に似ています)。欠点:無料版には検証機能がないため、30 日間の試用版を使用する必要がありました。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top