Java を使用してさまざまな XML ドキュメントを処理するにはどうすればよいでしょうか?

StackOverflow https://stackoverflow.com/questions/30627

  •  09-06-2019
  •  | 
  •  

質問

Java アプリケーションを使用してさまざまな XML ドキュメントを解析する最適な方法を探しています。私は現在、SAX とカスタム コンテンツ ハンドラーを使用してこれを実行していますが、うまく動作し、スムーズかつ安定しています。

私は、現在単一形式の XML ドキュメントを受信する同じプログラムに、さまざまな XML 要素を変更して 2 つの追加の XML ドキュメント形式を受信するオプションを検討することにしました。ContentHandler を、ドキュメントの最初の「startElement」に基づいて適切なものに置き換えることを望んでいました...しかし、まあ、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>

ストア.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>

マネージャー.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>
役に立ちましたか?

解決

私が理解しているように、問題は、解析する前に文書がどのような形式であるかわからないことです。デリゲート パターンを使用できます。DTD/XSD/などに対して検証を行っておらず、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...

他のヒント

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

最も単純なのは コモンズダイジェスター これは通常、構成ファイルを解析するために使用します。ただし、Java オブジェクトを扱いたい場合は、以下を参照してください。 キャスター, ジBX, JAXB, XMLBeans, Xストリーム, 、または同様のもの。Castor か JiBX が私のお気に入りです。

SAXParser を一度試してみましたが、 Xストリーム 二度と元には戻りませんでした。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 に変換して送信し、オブジェクトを再作成します。次に、それを使って好きなことをしてください。

のドキュメントを参照してください。 XMLReader.setContentHandler(), 、それはこう言います:

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

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

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

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

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

よりダイナミックな処理が必要な場合は、Sax よりも Stax アプローチの方が適しているでしょう。これはまだかなり低レベルです。もっとシンプルなアプローチが必要な場合は、XStream と JAXB が私のお気に入りです。ただし、マッピングするには非常に厳密なオブジェクトが必要です。

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

:-)

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

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

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

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top