ホームページ >バックエンド開発 >XML/RSS チュートリアル >4つのXML解析方法を詳しく解説
ご存知のとおり、XML を解析する方法は現在ますます増えていますが、主流の方法は DOM、SAX、JDOM、DOM4J の 4 つだけです
以下の 4 つが挙げられます。最初にメソッドの jar パッケージのダウンロード アドレス
DOM: 現在の Java JDK の xml-apis.jar パッケージに含まれています
SAX: http://www.php.cn/
JDOM: http: / /www.php.cn/
DOM4J: http://www.php.cn/
【メリット】
①アプリケーションがデータや構造を変更できる。
②アクセスは双方向であり、いつでもツリーを上下に移動して、データの任意の部分を取得および操作できます。
【欠点】
① 通常、階層構造を構築するには XML ドキュメント全体をロードする必要があり、多くのリソースを消費します。
2. SAX (Simple API for XML)
DOM か SAX を選びますか? XML ドキュメントを処理するために独自のコードを記述する必要がある開発者にとって、DOM または SAX 解析モデルの選択は非常に重要な設計上の決定です。 DOM はツリー構造を使用して XML ドキュメントにアクセスしますが、SAX はイベント モデルを使用します。
DOM パーサーは、XML ドキュメントをそのコンテンツを含むツリーに変換し、ツリーをトラバースできます。 DOM を使用してモデルを解析する利点は、開発者がツリー構築命令を呼び出すだけで済み、ナビゲーション API を使用して必要なツリー ノードにアクセスしてタスクを完了するだけで済むという点です。ツリー内の要素は簡単に追加および変更できます。ただし、DOM パーサーを使用する場合は XML ドキュメント全体を処理する必要があるため、特に大きな XML ファイルを処理する場合には、パフォーマンスとメモリの要件が比較的高くなります。 DOM パーサーは、そのトラバーサル機能により、XML ドキュメントを頻繁に変更する必要があるサービスでよく使用されます。
SAX パーサーはイベントベースのモデルを採用しており、XML ドキュメントを解析するときに一連のイベントをトリガーして、メソッドで指定されたタグが見つかったことをメソッドに通知できます。見つかった。 。 SAX では、どのタグを処理するかを開発者が決定できるため、通常、SAX のメモリ要件は低くなります。特に、開発者がドキュメントに含まれるデータの一部のみを処理する必要がある場合には、SAX のスケーラビリティがよりよく反映されます。ただし、SAX パーサーを使用する場合はコーディングがさらに難しくなり、同じドキュメント内の複数の異なるデータに同時にアクセスすることが困難になります。
【メリット】
① すべてのデータが処理されるのを待つ必要がなく、すぐに分析を開始できます。
②データは読み込み時にチェックされるだけで、メモリに保存する必要はありません。
③ドキュメント全体を解析せずに、特定の条件が満たされた場合に解析を停止できます。
④効率とパフォーマンスが高く、システムメモリよりも大きなドキュメントを解析できます。
【デメリット】
① TAGの処理ロジック(親子関係の維持など)をアプリケーションが担う必要があるため、ドキュメントが複雑になるほどプログラムも複雑になります。
②一方向ナビゲーション、ドキュメント階層を見つけることができず、同じドキュメント内のデータの異なる部分に同時にアクセスすることが困難で、XPath をサポートしていません。
3. JDOM (Java ベースのドキュメント オブジェクト モデル)
JDOM と DOM の間には 2 つの主な違いがあります。まず、JDOM は具象クラスのみを使用し、インターフェイスは使用しません。これにより、API がいくつかの点で簡素化されますが、柔軟性も制限されます。第 2 に、API は Collections クラスを広範囲に利用しており、これらのクラスにすでに精通している Java 開発者にとっての使用が簡素化されています。
JDOM ドキュメントには、その目的は「20% (またはそれ以下) の労力を使って 80% (またはそれ以上) の Java/XML 問題を解決する」ことであると記載されています (学習曲線に基づいて 20% を想定)。 JDOM はほとんどの Java/XML アプリケーションにとって確かに便利であり、ほとんどの開発者は API の方が DOM よりもはるかに理解しやすいと感じています。 JDOM には、ユーザーが XML で意味をなさないことを行うことを防ぐために、プログラムの動作に関するかなり広範なチェックも含まれています。ただし、基本以上のことを行うには、XML を十分に理解している必要があります (場合によってはエラーも理解する必要があります)。これは、DOM や JDOM インターフェイスを学習するよりも有意義な作業かもしれません。
JDOM 自体にはパーサーは含まれていません。通常、SAX2 パーサーを使用して入力 XML ドキュメントを解析および検証します (ただし、以前に構築された DOM 表現を入力として受け取ることもできます)。これには、JDOM 表現を SAX2 イベント ストリーム、DOM モデル、または XML テキスト ドキュメントに出力するコンバータが含まれています。 JDOM は、Apache ライセンスのバリアントに基づいてリリースされたオープン ソースです。
【利点】
①インターフェースの代わりに具体的なクラスを使用することで、DOM API が簡素化されます。
②Java開発者にとって便利なJavaコレクションクラスの多用。
【欠点】
①柔軟性が優れない。
②パフォーマンスが悪い。
DOM4J は完全に独立した開発結果を表しますが、当初は JDOM のインテリジェントな分岐でした。これには、統合された XPath サポート、XML スキーマ サポート、大規模ドキュメントまたはストリーミング ドキュメントのイベントベースの処理など、基本的な XML ドキュメント表現を超える多くの機能が組み込まれています。また、DOM4J API および標準 DOM インターフェイスを介した並列アクセス機能を備えたドキュメント表現を構築するためのオプションも提供します。 2000 年後半から開発が進められてきました。
これらすべての機能をサポートするために、DOM4J はインターフェイスと抽象基本クラス メソッドを使用します。 DOM4J は API で Collections クラスを多用しますが、多くの場合、パフォーマンスの向上やより直接的なコーディング アプローチを可能にする代替手段も提供します。直接的な利点は、DOM4J はより複雑な API の代償を払っていますが、JDOM よりもはるかに優れた柔軟性を提供することです。
柔軟性、XPath 統合、大規模ドキュメントの処理という目標を追加しながら、DOM4J の目標は JDOM と同じであり、Java 開発者にとっての使いやすさと直感的な操作です。また、JDOM よりも完全なソリューションとなることも目指しており、本質的にすべての Java/XML 問題を処理するという目標を達成します。その目標を達成しながら、アプリケーションの不正な動作の防止には JDOM ほど重点を置きません。
DOM4J は、優れたパフォーマンス、強力な機能、そして非常に使いやすい、非常に優れた Java XML API であり、オープンソース ソフトウェアでもあります。最近では、XML の読み書きに DOM4J を使用する Java ソフトウェアが増えています。特に、Sun の JAXM も DOM4J を使用していることは注目に値します。
【利点】
① Java コレクション クラスを多用しており、 Java 開発者向けに、パフォーマンスを向上させるための代替手段をいくつか提供します。
②XPathをサポートします。
③非常に優れたパフォーマンスを持っています。
【欠点】
① インターフェースを多用し、API が比較的複雑。
1. DOM4J は最高のパフォーマンスを持ち、Sun の JAXM も DOM4J を使用しています。現在、DOM4J は多くのオープンソース プロジェクトで広く使用されています。たとえば、有名な Hibernate も XML 設定ファイルを読み取るために DOM4J を使用しています。移植性を考慮しない場合は、DOM4J を使用してください
2. JDOM と DOM は、10M ドキュメントのテスト時にメモリ オーバーフローが発生するなど、パフォーマンス テストではパフォーマンスが低下しましたが、移植性はあります。小さなドキュメントの場合は、DOM と JDOM の使用を検討する価値があります。JDOM の開発者は、正式リリース前にパフォーマンスの問題に重点を置く予定であると述べていますが、パフォーマンスの観点からは、実際には推奨できるものは何もありません。さらに、DOM は依然として非常に優れた選択肢です。 DOM 実装は、多くのプログラミング言語で広く使用されています。これは、他の多くの XML 関連標準の基礎でもあり、(非標準ベースの Java モデルとは対照的に) W3C によって公式に推奨されているため、特定の種類のプロジェクト (たとえば、 JavaScript の DOM)。
3. SAX のパフォーマンスが向上しますが、これはその特定の解析方法 (イベント駆動型) に依存します。 SAX は受信 XML ストリームを検出しますが、それをメモリにロードしません (もちろん、XML ストリームが読み取られるとき、一部のドキュメントはメモリ内に一時的に隠蔽されます)。
私の意見: XML ドキュメントが大きく、移植性を考慮しない場合は DOM4J を使用することをお勧めします。XML ドキュメントが小さい場合、保存せずにタイムリーに処理する必要がある場合は JDOM を使用することをお勧めします。データの場合は、SAX を考慮してください。ただし、いずれの場合も、自分に合った方法が最適であるということは同じです。時間が許せば、4 つの方法をすべて試して、自分に合った方法を選択することをお勧めします。
スペースを節約するため、ここでは XML ドキュメントを作成する 4 つの方法とその違いについては説明しません。完全なプロジェクトが必要な場合は、XML ドキュメントを作成するためのコードのみを示します。 + XML の解析 + 比較のテスト)。
ここでは、解析する例として次の XML コンテンツを取り上げます:
<?xml version="1.0" encoding="UTF-8"?> <users> <user id="0"> <name>Alexia</name> <age>23</age> <sex>Female</sex> </user> <user id="1"> <name>Edward</name> <age>24</age> <sex>Male</sex> </user> <user id="2"> <name>wjm</name> <age>23</age> <sex>Female</sex> </user> <user id="3"> <name>wh</name> <age>24</age> <sex>Male</sex> </user> </users>
まず、XML ドキュメント解析用のインターフェイスを定義します:
/** * @author Alexia * * 定义XML文档解析的接口 */ public interface XmlDocument { /** * 解析XML文档 * * @param fileName * 文件全路径名称 */ public void parserXml(String fileName); }
package com.xml; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; /** * * DOM 解析XML文档 */ public class DomDemo implements XmlDocument { private Document document; public void parserXml(String fileName) { try { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); Document document = db.parse(fileName); NodeList users = document.getChildNodes(); for (int i = 0; i < users.getLength(); i++) { Node user = users.item(i); NodeList userInfo = user.getChildNodes(); for (int j = 0; j < userInfo.getLength(); j++) { Node node = userInfo.item(j); NodeList userMeta = node.getChildNodes(); for (int k = 0; k < userMeta.getLength(); k++) { if(userMeta.item(k).getNodeName() != "#text") System.out.println(userMeta.item(k).getNodeName() + ":" + userMeta.item(k).getTextContent()); } System.out.println(); } } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
package com.xml; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.StringWriter; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import javax.xml.transform.OutputKeys; import javax.xml.transform.Result; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.sax.SAXTransformerFactory; import javax.xml.transform.sax.TransformerHandler; import javax.xml.transform.stream.StreamResult; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.AttributesImpl; import org.xml.sax.helpers.DefaultHandler; /** * * SAX 解析XML文档 */ public class SaxDemo implements XmlDocument { public void parserXml(String fileName) { SAXParserFactory saxfac = SAXParserFactory.newInstance(); try { SAXParser saxparser = saxfac.newSAXParser(); InputStream is = new FileInputStream(fileName); saxparser.parse(is, new MySAXHandler()); } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } class MySAXHandler extends DefaultHandler { boolean hasAttribute = false; Attributes attributes = null; public void startDocument() throws SAXException { // System.out.println("文档开始打印了"); } public void endDocument() throws SAXException { // System.out.println("文档打印结束了"); } public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if (qName.equals("users")) { return; } if (qName.equals("user")) { return; } if (attributes.getLength() > 0) { this.attributes = attributes; this.hasAttribute = true; } } public void endElement(String uri, String localName, String qName) throws SAXException { if (hasAttribute && (attributes != null)) { for (int i = 0; i < attributes.getLength(); i++) { System.out.print(attributes.getQName(0) + ":" + attributes.getValue(0)); } } } public void characters(char[] ch, int start, int length) throws SAXException { System.out.print(new String(ch, start, length)); } }
package com.xml; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.List; import org.jdom2.Document; import org.jdom2.Element; import org.jdom2.JDOMException; import org.jdom2.input.SAXBuilder; import org.jdom2.output.XMLOutputter; /** * * JDOM 解析XML文档 * */ public class JDomDemo implements XmlDocument { public void parserXml(String fileName) { SAXBuilder builder = new SAXBuilder(); try { Document document = builder.build(fileName); Element users = document.getRootElement(); List userList = users.getChildren("user"); for (int i = 0; i < userList.size(); i++) { Element user = (Element) userList.get(i); List userInfo = user.getChildren(); for (int j = 0; j < userInfo.size(); j++) { System.out.println(((Element) userInfo.get(j)).getName() + ":" + ((Element) userInfo.get(j)).getValue()); } System.out.println(); } } catch (JDOMException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }