1

メモリ内のバイト ストリームとして保持されている XML ドキュメントを、ファイル システム内に配置されている XSD に対して検証したい状況があります。XML ファイルでファイル名を明示的に指定することは避けたいと思いますが、その代わりに、検証のために 1 つ以上の XSD ファイルのカタログを使用するよう XML パーサーに指示します。

DocumentBuilder プロバイダー (Guice 3.0 用) を作成しようとすると、次のようになります。

public class ValidatingDocumentBuilderProvider implements
        Provider<DocumentBuilder> {

    static final String JAXP_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
    static final String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema";
    static final String JAXP_SCHEMA_SOURCE = "http://java.sun.com/xml/jaxp/properties/schemaSource";

    Logger log = getLogger(ValidatingDocumentBuilderProvider.class);

    DocumentBuilderFactory dbf;

    public synchronized DocumentBuilder get() { // dbf not thread-safe

        if (dbf == null) {
            log.debug("Setting up DocumentBuilderFactory");

            // http://download.oracle.com/javaee/1.4/tutorial/doc/JAXPDOM8.html
            dbf = DocumentBuilderFactory.newInstance();
            dbf.setNamespaceAware(true);
            dbf.setValidating(true);
            dbf.setAttribute(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA);
            // parser should look for schema reference in xml file

            // Find XSD's in current directory.

            FilenameFilter fileNameFilter = new FilenameFilter() {

                public boolean accept(File dir, String name) {
                    return name.toLowerCase().endsWith(".xsd");
                }
            };
            File[] schemaFiles = new File(".").listFiles(fileNameFilter);

            dbf.setAttribute(JAXP_SCHEMA_SOURCE, schemaFiles);

            log.debug("{} schema files found", schemaFiles.length);
            for (File file : schemaFiles) {
                log.debug("schema file: {}", file.getAbsolutePath());
            }

        }

        try {
            return dbf.newDocumentBuilder();
        } catch (ParserConfigurationException e) {
            throw new RuntimeException("get DocumentBuilder", e);
        }
    }
}

(そして、ファイル名も試しました)。Eclipse は XSD を受け入れます。カタログに入れると、ここで扱う XML を検証できます。

肉眼では、検証しようとするとパーサーが一時的に停止するように見えます。これは、ネットワーク ルックアップである可能性があります。

-Djaxp.debug=1これらの行のみを追加します

JAXP: find factoryId =javax.xml.parsers.DocumentBuilderFactory
JAXP: loaded from fallback value: com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl
JAXP: created new instance of class com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl using ClassLoader: null

JDK 6 のパーサーに何をしているのかを教えてもらうにはどうすればよいですか? それができない場合、提供された XSD が選択されていない理由を確認するために、内部の XML カタログの使用状況を調べるにはどうすればよいですか?

私が見落とした明らかなことは何ですか?

4

1 に答える 1

0

あなたは言う

XML ファイルでファイル名を明示的に指定することは避けたいと考えています。

では、パーサーはどのようにして適切なスキーマを選択できるのでしょうか?

試すことができるのは、利用可能なすべてのスキーマ リソースに基づいてSchemaを使用して を作成し、それをドキュメント ビルダー ファクトリにアタッチすることです。SchemaFactoryパーサーは、この「スーパー スキーマ」に対してドキュメントを自動的に検証します。

一連のスキーマに内部的な依存関係 (つまり、インポートまたはインクルード) がある場合は、相対 URL または特殊なリゾルバーを使用して、それらの参照が正しく解決されていることを確認してください。

アップデート:

これを読んだ後、http://java.sun.com/j2ee/1.4/docs/tutorial/doc/JAXPDOM8.htmlをもう少し注意深く読んだ後、あなたのアプローチは私の提案と同じ効果があるはずだと気づきました。 n になります。私が説明したことは非常にうまく機能しているとしか言えません。

于 2011-10-03T10:33:17.947 に答える