4

JavaとSAXパーサーを使用したXML解析は初めてです。私は非常に大きなXMLファイルを持っており、そのサイズのためにSAXパーサーを使用するようにアドバイスされています。タスクの一部の解析が完了し、期待どおりに機能します。現在、XMLジョブには1つのタスクが残っています。それは、ユーザーの要求に応じていくつかのノードを削除/更新することです。

名前ですべてのタグを検索したり、data属性を変更したりすることができます。SAXでこれらを実行できる場合は、削除も可能です。

サンプルXMLは、場合によってはいくつかの機能を説明しています。ユーザーの入力は「ケース」の名前(case1case2)です。

<ruleset>
    <rule id="1">
        <condition>
            <case1>somefunctionality</case1>
            <allow>true</allow>
        </condition>
    </rule>
    <rule id="2">
        <condition>
            <case2>somefunctionality</case2>
            <allow>false</allow>
        </condition>
    </rule>
</ruleset>

ユーザーがタグだけでなく、これらのケースの1つ(たとえばcase1)を削除したい場合は、タグ全体を削除する必要があります。削除する場合、XMLは次のようになります。case1rulecase1

<ruleset>
    <rule id="2">
        <condition>
            <case2>somefunctionality</case2>
            <allow>false</allow>
        </condition>
    </rule>
</ruleset>

私の質問は、これはSAXを使用して実行できますか?現時点では、DOMやその他のパーサーを使用することはできません。他のオプションだけがさらに悪いです:文字列検索。SaxParserを使用してどのように行うことができますか?

4

3 に答える 3

6

としてお試しください

    XMLReader xr = new XMLFilterImpl(XMLReaderFactory.createXMLReader()) {
        private boolean skip;

        @Override
        public void startElement(String uri, String localName, String qName, Attributes atts)
                throws SAXException {
            if (qName.equals("rule")) {
                if (atts.getValue("id").equals("1")) {
                    skip = true;
                } else {
                    super.startElement(uri, localName, qName, atts);
                    skip = false;
                }
            } else {
                if (!skip) {
                    super.startElement(uri, localName, qName, atts);
                }
            }
        }

        public void endElement(String uri, String localName, String qName) throws SAXException {
            if (!skip) {
                super.endElement(uri, localName, qName);
            }
        }

        @Override
        public void characters(char[] ch, int start, int length) throws SAXException {
            if (!skip) {
                super.characters(ch, start, length);
            }
        }
    };
    Source src = new SAXSource(xr, new InputSource("test.xml"));
    Result res = new StreamResult(System.out);
    TransformerFactory.newInstance().newTransformer().transform(src, res);

出力

<?xml version="1.0" encoding="UTF-8"?><ruleset>
    <rule id="2">
        <condition>
            <case2>somefunctionality</case2>
            <allow>false</allow>
        </condition>
    </rule>
</ruleset>
于 2012-12-13T01:25:20.503 に答える
0

SAXは、XMLの読み取り/解析に最も一般的に使用されます。しかし、SAXを使用してファイルを書き込む方法に関する記事があります。そして、その章はオンラインで利用できるようです-参照してください:

http://xmlwriter.net/sample_chapters/Professional_XML/31100604.shtml

[この記事の日付は1999年なので、古いバージョンのSAXを使用していますが、概念は引き続き適用されます]

基本的な考え方は、カスタムDocumentHandler/ContentHandlerを作成することです。SAXイベントを受信するたびに、イベントをシリアル化してストリーム/ファイルなどに書き込みます。したがって、入力ドキュメントをsaxイベントのソースとして使用し、これらのイベントをXMLOutputterに転送します。

難しいのは、XMLドキュメントをSAXイベントのストリームに解析し、XMLOutputterを駆動して、入力ファイルの正確なコピーを生成できるようになることです。それが機能するようになったら、ルールを読んでそれらを使用して出力ファイルを変更する編集ロジックに移動できます。

DOM、JDOM、XSLTなどよりもはるかに多くの作業が必要ですが、ドキュメント全体をメモリに保存する必要がないため、状況に役立つ場合があります。

于 2012-12-12T20:24:33.737 に答える
0

構築する必要があるのはSAXイベントバッファーです。

要素にアクセスするときは、その<rule>要素(または要素を再生成するために必要な情報)と、その要素と削除する「ケース」との間に発生する他のすべてのイベントを保存する必要があります。

保存した「ルール」が削除する必要のあるルールと同じである場合は、情報を破棄して続行します。

保存した「ルール」が削除する必要のあるものでない場合は、保存したサックスイベントを再生成して続行する必要があります。

于 2012-12-12T20:11:06.710 に答える