4

私はこれについて興味があります:効率を上げるためにSaxパーサーを使用する必要がある場合(それは大きなファイルです)。通常、私は次のようなものを使用します。

public class Example extends DefaultHandler
{
    private Stack stack = new Stack ();

    public void startElement (String uri, String local, String qName, Attributes atts) throws SAXException
    {
        stack.push (qName);
    }

    public void endElement (String uri, String local, String qName) throws SAXException
    {
        if ("line".equals (qName))
            System.out.println ();

        stack.pop ();
    }

    public void characters (char buf [], int offset, int length) throws SAXException
    {
        if (!"line".equals (stack.peek ()))
            return;

        System.out.write (new String (buf, offset, length));
    }
}

ここから取った例。

SaxはすでにVisitorPatternの実装ですが、私の場合は、すべての要素のコンテンツを取得し、要素自体の性質に応じてそれを使用して何かを行う必要があります。

私の典型的なXMLファイルは次のようなものです。

<?xml version="1.0" encoding="utf-8"?>
<labs xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <auth>
        <uid> </uid>
        <gid> </gid>
        <key> </key>
    </auth>
    <campaign>
        <sms>
            <newsletter>206</newsletter>
            <message>
                <from>Da Definire</from>
                <subject>Da definire</subject>
                <body><![CDATA[Testo Da Definire]]></body>
            </message>
            <delivery method="manual"></delivery>
            <recipients>
                <db>276</db>
                <filter>
                    <test>1538</test>
                </filter>
                <new_recipients>
                    <csv_file>Corso2012_SMS.csv</csv_file>
                </new_recipients>
            </recipients>
        </sms>
    </campaign>
</labs>

csv_fileノードにいるときは、ファイル名を取得してそのファイルからユーザーをアップロードする必要があります。私がいるfilter/test場合は、フィルターが存在するかどうかを確認する必要があります。SAXでビジターパターンを適用する方法はありますか?

4

2 に答える 2

1

SAXパーサーにを含めるだけMap<String, ElementHandler>で、要素名のElementHandlerを登録できます。葉の要素のみに関心があると仮定します。

  • 要素が開始するたびに、マップにこの要素名のハンドラーがあるかどうかを確認し、バッファーをクリアします。
  • が呼び出されるたびcharacters()に、文字をバッファに追加します(前の要素の開始のハンドラがあった場合)
  • 要素が終了するたびに、前の要素の開始のハンドラーがあった場合は、バッファーの内容を使用してハンドラーを呼び出します

次に例を示します。

private ElementHandler currentHandler;
private StringBuilder buffer = new StringBuilder();
private Map<String, ElementHandler> handlers = new HashMap<String, ElementHandler>();

public void registerHandler(String qName, ElementHandler handler) {
    handlers.put(qName, handler);
}    

public void startElement (String uri, String local, String qName, Attributes atts) throws SAXException {
    currentHandler = handlers.get(qName);
    buffer.delete(0, buffer.length());
}

public void characters (char buf [], int offset, int length) throws SAXException {
    if (currentHandler != null) {
        buffer.append(buf, offset, length);
    }
}

public void endElement (String uri, String local, String qName) throws SAXException {
    if (currentHandler != null) {
        currentHandler.handle(buffer.toString();
    }
}
于 2012-06-01T14:49:03.247 に答える
0

StAXを忘れないでください。ビジターパターンを簡単にすることはおそらくないでしょうが、ドキュメントが比較的単純で、すでにストリーミングを計画している場合は、SAXよりも単純なプログラミングモデルがあります。解析されたストリーム内のイベントを一度に1回繰り返し、選択したとおりに無視または処理します。

于 2012-06-02T00:04:36.167 に答える