2

Java アプリケーションを使用してさまざまな XML ドキュメントを解析するための最良の方法を探しています。私は現在、SAX とカスタム コンテンツ ハンドラーを使用してこれを行っていますが、うまく機能します。

私は、現在 1 つの形式の XML ドキュメントを受け取り、さまざまな XML 要素の変更を加えた 2 つの追加の XML ドキュメント形式を受け取る、同じプログラムを持つオプションを検討することにしました。ドキュメントの最初の「startElement」に基づいて、ContentHandler を適切なものと交換したいと思っていましたが、ええと、ContentHandler が設定されドキュメントが解析されます。

... constructor ...
{
SAXParserFactory spf = SAXParserFactory.newInstance();

try {
SAXParser sp = spf.newSAXParser();
parser = sp.getXMLReader();
parser.setErrorHandler(new MyErrorHandler());
} catch (Exception e) {} 

... parse StringBuffer ...
try {
parser.setContentHandler(pP);
parser.parse(new InputSource(new StringReader(xml.toString())));
return true;
} catch (IOException e) {
    e.printStackTrace();
} catch (SAXException e) {
    e.printStackTrace();
}
...

そのため、最初にできると思っていた方法でこれを行うことができるようには見えません。

そうは言っても、私はこれを完全に間違って見ていますか?複数の個別の XML ドキュメントを同じ XML 処理コードで解析する最適な方法は何ですか? 以前、もっと一般的な投稿で質問しようとしましたが、漠然としすぎていたと思います。これらの XML ドキュメントはかなり大きく、システムは数分ごとに約 1200 を受信するため、速度と効率のために DOM を実際に調べたことはありません。それはただの一方通行の情報発信です

この質問を長くしすぎて、混乱を招きます。以下は、単一の SAX、StAX、または ?? にしたいいくつかのさまざまな XML ドキュメントのモックアップです。パーサーはきれいに対処します。

製品.xml:

<products>
<product>
  <id>1</id>
  <name>Foo</name>
<product>
  <id>2</id>
  <name>bar</name>
</product>
</products>

store.xml:

<stores>
<store>
  <id>1</id>
  <name>S1A</name>
  <location>CA</location>
</store>
<store>
  <id>2</id>
  <name>A1S</name>
  <location>NY</location>
</store>
</stores>

manager.xml:

<managers>
<manager>
  <id>1</id>
  <name>Fen</name>
  <store>1</store>
</manager>
<manager>
  <id>2</id>
  <name>Diz</name>
  <store>2</store>
</manager>
</managers>
4

9 に答える 9

3

私が理解しているように、問題は、解析する前にドキュメントの形式がわからないことです。デリゲート パターンを使用できます。DTD/XSD/etcetera に対して検証を行っておらず、DefaultHandler が状態を保持しても問題ないと想定しています。

public class DelegatingHandler extends DefaultHandler {

    private Map<String, DefaultHandler> saxHandlers;
    private DefaultHandler delegate = null;

    public DelegatingHandler(Map<String, DefaultHandler> delegates) {
        saxHandlers = delegates;
    }

    @Override
    public void startElement(String uri, String localName, String name,
            Attributes attributes) throws SAXException {
       if(delegate == null) {
           delegate = saxHandlers.get(name);
       }
       delegate.startElement(uri, localName, name, attributes);
    }

    @Override
    public void endElement(String uri, String localName, String name)
            throws SAXException {
        delegate.endElement(uri, localName, name);
    }

//etcetera...
于 2008-08-27T17:38:38.753 に答える
2

XMLReader.setContentHandler()のドキュメントを参照してください。

アプリケーションは、解析の途中で新しいハンドラまたは別のハンドラを登録する場合があり、SAX パーサーは新しいハンドラをすぐに使用し始める必要があります。

したがって、 XML リーダーの変更に基づいてSelectorContentHandler、最初のイベントまでイベントを消費し、最初の開始要素イベントを新しいコンテンツ ハンドラーに渡すを作成できるはずです。コンストラクターでをに渡すだけです。すべてのイベントを語彙固有のコンテンツ ハンドラーに渡す必要がある場合は、イベントをキャッシュしてから渡す必要がありますが、ほとんどの場合、これは必要ありません。startElementContentHandlerXMLReaderSelectorContentHandlerSelectorContentHandler

余談ですが、私は最近、ほぼすべてのプロジェクトで XML ja を処理するためにXOMを使用しましたが、これまでのところパフォーマンスは問題ではありませんでした。

于 2008-08-27T18:58:49.450 に答える
2

やりたいことはうまく説明できましたが、その理由はうまく説明できませんでした。Java オブジェクトの XML へのマーシャリングおよび XML からのマーシャリング解除を簡素化する XML フレームワークがいくつかあります。

最も単純なのはCommons Digesterで、私は通常、構成ファイルを解析するために使用します。しかし、Java オブジェクトを扱いたい場合は、CastorJiBXJAXBXMLBeansXStream、または同様のものを検討する必要があります。Castor または JiBX は、私の 2 つのお気に入りです。

于 2008-08-27T17:22:33.770 に答える
2

私は SAXParser を 1 回試しましたが、XStreamを見つけた後は二度と使用しませんでした。XStream を使用すると、Java オブジェクトを作成して XML に変換できます。それらを送信し、XStream を使用してオブジェクトを再作成します。非常に使いやすく、高速で、きれいな XML を作成します。

いずれにせよ、XML ファイルから受信するデータを知る必要があります。それらをさまざまな方法で送信して、使用するパーサーを知ることができます。または、すべてを保持できるデータ オブジェクトがありますが、1 つの構造 (製品/店舗/管理者) のみが入力されます。たぶん次のようなもの:

public class DataStructure {

    List<ProductStructure> products;

    List<StoreStructure> stors;

    List<ManagerStructure> managers;

    ...

    public int getProductCount() {
        return products.lenght();
    }

    ...
}

XStream を使用して XML に変換し、オブジェクトを送信して再作成します。それからあなたがそれでやりたいことをしてください。

于 2008-08-27T17:30:23.360 に答える
1

JAXB . XML バインディングのための Java アーキテクチャ。基本的に、XML レイアウトを定義する xsd を作成します (DTD も使用できると思います)。次に、XSD を JAXB コンパイラに渡すと、コンパイラは Java クラスを作成して、XML ドキュメントを Java オブジェクトにマーシャリングおよびアンマーシャリングします。それは本当に簡単です。

ところで、jaxb には、結果のクラスを配置するパッケージ名などを指定するコマンド ライン オプションがあります。

于 2008-08-27T17:20:14.523 に答える
0

興味深いことに、Stax の使用を望んでいる StaxMan に同意します。これは、現在使用しているプッシュではなく、プル ベースのパーサーです。ただし、これにはコードにいくつかの大幅な変更が必要になります。

于 2009-01-08T14:32:31.537 に答える
0

より動的な処理が必要な場合は、おそらく Sax よりも Stax の方がうまくいくでしょう。それはまだかなり低レベルです。より単純なアプローチが必要な場合は、XStream と JAXB が私のお気に入りです。ただし、マッピング先として非常に厳格なオブジェクトが必要です。

于 2009-01-08T04:00:51.920 に答える
0

:-)

はい、私はスタックスに偏見を持っています。しかし、前述したように、多くの場合、データ バインディングはストリーミング ソリューションよりも便利です。しかし、必要なストリーミングであり、(複数のフィルタリング段階の) パイプライン処理が必要ない場合、Stax は SAX よりも単純です。

もう 1 つ: XOM は (代替手段として) 優れていますが、「ドキュメント中心」の xml (~= xhtml ページ、docbook、オープン オフィス ドキュメント) を扱っていない場合、多くの場合、ツリー モデルは使用するのに適切ではありません。データ交換、構成ファイルなどの場合、データバインディングはより便利で、より効率的で、より自然です。これらのユース ケースでは、DOM のようなツリー モデルにはノーと言いましょう。だから、JAXB、XStream、JibX がいい。または、さらに味わいたい場合は、ダイジェスター、トウゴマ、xmlbeans を使用します。

于 2009-01-27T20:26:30.253 に答える
0

VTD-XML は、負荷の高い XML 処理に最適な XML 処理テクノロジとして知られています。証明については、以下のリファレンスを参照してください

http://sdiwc.us/digitlib/journal_paper.php?paper=00000582.pdf

于 2016-04-09T19:24:20.560 に答える