2

Apache Xerces SAX2 検証パーサーを使用して、非常に単純な XML ファイルを解析および検証しようとしています。DTD は XML ファイルから参照され、単純なエンティティ リゾルバーは DTD ファイルの適切な InputStream を正常に返すことができます。私は非常に基本的なタグ構造を持っています。名前を付ける必要はないので、単純に XML タグに文字を付けます。主なタグは A です。A タグ内に 0 個以上の B が存在する可能性がありますが、B のみです。そして、B の中に 0 個以上の C があります。したがって、適切な XML は次のようになります。

<A>
<B><C>somecharacters</C></B>
</A>

単体テストを作成したところ、奇妙な動作が発生しました。上記と同様の XML をパーサーに渡して、一致する開始タグがなく、親要素 B がない C の終了タグのみを指定すると、パーサーは DTD 検証エラーを報告します。以下は、DTD に従って意図的に無効にした XML の例です。

<A>
<C>somecharacters</C></B>
</A>

この XML フラグメントが整形式でないことは明らかです。残念ながら (または、SAX パーサーで何かがわかりません)、パーサーは C タグに対して ContentHandler の startElement メソッドを呼び出し、その後、C タグ内の文字に対して characters メソッドを呼び出します。DTD は、A タグは B タグのみを子として持つことができ、C は最初に B 内にネストする必要があるため、C を持たないことを明確に述べています。私が理解していないのは、ネストされた C が適切な場所にないことに気付いた後、パーサーが文字メソッドを呼び出す理由です。

私の ContentHandler メソッドのアプリケーション ロジックは、タグが DTD に従ってネストされているという前提に依存しています。これら 3 つのメソッドに null チェッカーとエラー処理コードを入力したくありません。これは DTD バリデーターの仕事であると想定しているためです。

パーサーをセットアップするための私のコードは(例外処理部分は関係ありません):

    private static final String VALIDATION_FEATURE = "http://xml.org/sax/features/validation";
    private static final String SAX_PARSER_IMPLEMENTATION = "org.apache.xerces.parsers.SAXParser";
    ......
    XMLReader parser = XMLReaderFactory.createXMLReader(SAX_PARSER_IMPLEMENTATION);
    parser.setFeature(VALIDATION_FEATURE, true);
    parser.setErrorHandler(new CustomErrorHandler());
    parser.setEntityResolver(entityResolver);
    parser.setContentHandler(handler);

    InputSource inputSource = new InputSource(stream);
    try {
        parser.parse(inputSource);
    } catch (IOException e) {
        throw new ControlFileReadException("Error while parsing the control file.", e);
    } catch (SAXException e) {
        if (e.getCause() instanceof IncorrectCounterNameException) {
            throw new IncorrectCounterNameException(e.getCause());
        } else {
            throw e;
        }
    }

    private final class CustomErrorHandler implements ErrorHandler {
    public void warning(SAXParseException spe) throws SAXException {
        throw spe;
    }

    public void fatalError(SAXParseException spe) throws SAXException {
        throw spe;
    }

    public void error(SAXParseException spe) throws SAXException {
        throw spe;
    }
}

どんな助けでも大歓迎です!

4

0 に答える 0