2008-08-27 5 views
2

私は、Javaアプリケーションを使用してさまざまなXML文書を解析する最善の方法を探しています。私は現在、SAXとカスタムコンテンツハンドラでこれをやっています。それは素晴らしい - zippyで安定しています。Javaを使用してさまざまなXML文書を処理する方法を教えてください。

私は、同じプログラムを持っていて、現在単一のフォーマットの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文書を解析する最善の方法は何ですか? I tried to ask in a more general post earlier... but, I think I was being too vague。これらのXML文書はかなり大きく、システムは数分おきに約1200を受け取るため、速度と効率の観点から、私はDOMを見たことはありません。それはちょうど片道の情報の送信です

この質問を長すぎると私の混乱に追加するには。以下は、私が単一のSAX、StAX、またはを持っていたいと思ういくつかの様々なXML文書のモックアップです。パーサーはきれいに対処する。

のproducts.xml:

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

stores.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> 

managers.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> 

答えて

3

私が理解しているように、問題は、ドキュメントがどのような形式であるかわからないことです。デリゲートパターンを使用することができます。私は、あなたがDTD/XSD/etcに対して妥当性を検証していないと仮定しており、DefaultHandlerが状態を持つことがOKであることを前提としています。

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... 
1

JAXB。 XMLバインディングのためのJavaアーキテクチャー基本的には、XMLレイアウトを定義するxsdを作成します(私はあなたもDTDを使うことができると信じています)。次に、XSDをJAXBコンパイラに渡します。コンパイラは、XML文書をJavaオブジェクトにマーシャリングおよび非マーシャルするJavaクラスを作成します。それは本当に簡単です。

ところで、あなたはその結果のクラスを配置したいパッケージ名を指定するには、JAXBするためのコマンドラインオプションが

+0

については、以下のリファレンスを参照してください。また、DTDベースのソリューションが無効であるように彼は解析を開始するまで、彼は個々のxmlのフォーマットを知らない! –

+0

私は、DTDは大きなノーであることに同意しますが、JAXBはStax XMLStreamReaderを指定するとサブツリーをバインドすることもできます。さらに、Java POJOはメモリ内ではるかに軽く、一般に生のXML(またはDOMはXMLの3倍から5倍のDOM! POJOに注釈を付けてJAXBを使用することはかなり合理的です – StaxMan

2

がなどがあるあなたは、なぜあなたが何をしたいのかを説明するのは良い仕事をしてなくてきました。 JavaオブジェクトをXMLとの間で整列化および非整列化する作業を簡素化するXMLフレームワークがいくつかあります。

私が通常設定ファイルを解析するのに最も簡単なのはCommons Digesterです。しかし、Javaオブジェクトを扱う場合は、CastorJiBXJAXBXMLBeansXStream、またはそれに類するものを参照してください。 CastorまたはJiBXは私の2つのお気に入りです。

2

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

どちらの方法でも、XMLファイルからどのようなデータを受信するのかを知る必要があります。さまざまな方法でそれらを送信して、どのパーサーを使用するかを知ることができます。または、1つの構造だけがすべて格納されるデータオブジェクトを作成します(product/store/managers)。おそらく次のようなものでしょう:

public class DataStructure { 

    List<ProductStructure> products; 

    List<StoreStructure> stors; 

    List<ManagerStructure> managers; 

    ... 

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

    ... 
} 

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

2

XMLReader.setContentHandler()のマニュアルを参照してください、それは言う:

アプリケーションでは、解析の途中で新規または別のハンドラを登録することができ、SAXパーサはただちにこのハンドラの使用を開始しなければなりません。

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

私は最近、ほとんどのプロジェクトでXMLを扱うためにXOMを使用しましたが、これまでのところパフォーマンスは問題ではありませんでした。

0

もっとダイナミックな処理が必要な場合は、おそらくStaxアプローチがSaxよりもうまくいくでしょう。 これはまだかなり低レベルです。簡単なアプローチが必要な場合は、XStreamとJAXBが私のお気に入りです。しかし、彼らはマップするために非常に堅いオブジェクトを必要とします。

0

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

0

:-)

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

もう1つ:XOMほど良い(wrtの代替品)、しばしばTree Modelはあなたが "ドキュメント中心"のxml(〜= xhtmlページ、docbook、open office docs)。 データ交換の場合、設定ファイルなどのデータバインディングは、より便利で、より効率的で、より自然です。これらのユースケースについては、DOMのようなツリーモデルにnoと答えてください。 JAXB、XStream、JibXは良いです。または、より多くの味、消化器、ひましも、xmlbeansを取得しました。

0

VTD-XMLは、頑丈なXML処理のための最高のXML処理技術として知られています。ポスターは、すでに彼はので期待ボリューム(1200数分ごと)のSAXのようなストリームパーサを使用することを好むことが示された証拠

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

関連する問題