01. はじめにXMLは拡張マークアップ言語であり、開発者がデータの送信と保存に広く利用されています。XMLの定義は比較的単純で、通常は文書内の情報を記述するために以下のように始まります。 <?xml version="1.0" encoding="UTF-8"?> たとえば、次の簡単なドキュメント。 <?xml version="1.0" encoding="UTF-8"?> <site> <name>博客网站</name> <url>https://www.pzblog.cn</url> <desc>技术学习网站</desc> </site> ここで、site、name、url、desc はタグ名を表し、content はタグに対応する値を表します。 XML はプラットフォーム、言語、システムに依存しないという特徴があり、システム間のデータ転送が非常に容易になるため、開発者の間で広く普及しています。 実際、XML は 1996 年の導入以来、徐々に普遍的なデータ交換形式になってきました。 異なるプログラミング言語でも、XML の解析には基本的に同じロジックが使用されますが、構文が若干異なる場合があります。 今日は、Java プログラミング言語を使用して XML を解析する方法と、それぞれの利点と欠点について一緒に学習します。 分析の結果、Java プログラムを使用して XML ファイルを解析する最も一般的な 4 つの方法は次のとおりです。 以下では、次の XML ファイルを例として、各メソッドの解析実装を紹介します。 <?xml version="1.0" encoding="utf-8" ?> <class> <student id="1"> <name>张三</name> <gender>男</gender> <age>26</age> </student> <student id="2"> <name>里斯</name> <gender>男</gender> <age>36</age> </student> <student id="3"> <name>王五</name> <gender>女</gender> <age>24</age> </student> </class> 02. DOM解析DOMはDocument Object Model(ドキュメントオブジェクトモデル)の略です。Javaでサポートされている最も初期のXML解析手法の一つです。サードパーティのパッケージに依存せずに高速な解析を実現でき、コードもシンプルにプログラミングできます。 DOM は XML ドキュメントを解析するときに、ドキュメント全体をメモリにロードして階層構造を構築するため、次のような大きな利点があります。 - 1. XML 内の任意のノード データを迅速に走査しながら、アプリケーションがデータと構造を変更できるようにします。
- 2. いつでもツリーを上下に移動して、ツリーの任意の部分のデータにアクセスし、操作することができます。
もちろん、欠点もあります。 - 小さな XML ドキュメントを読み込むことは問題ありませんが、大きな XML ドキュメントを読み込むと大量のメモリが消費され、メモリ オーバーフローが発生するリスクがあります。
一般に、DOM 解析方法は、データ量が比較的少ない XML ドキュメントには十分です。 実装プロセスは次のとおりです。 import org.w3c.dom.*; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import java.io.InputStream; public class DomDemo { public static void main(String[] args) { // 1.获取xml文件流InputStream inputStream = DomDemo.class.getClassLoader().getResourceAsStream("demo.xml"); // 2.创建DocumentBuilderFactory对象DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); // 3.创建DocumentBuilder对象try { DocumentBuilder builder = factory.newDocumentBuilder(); Document d = builder.parse(inputStream); NodeList stdList = d.getElementsByTagName("student"); for (int i = 0; i <stdList.getLength() ; i++) { Node std = stdList.item(i); // 遍历标签属性NamedNodeMap attrs = std.getAttributes(); for(int j=0; j< attrs.getLength(); j++){ Node attr = attrs.item(j); System.out.println(attr.getNodeName()+":"+attr.getNodeValue()); } // 遍历标签子节点NodeList childNodes = std.getChildNodes(); for (int k = 0; k <childNodes.getLength() ; k++) { if (childNodes.item(k).getNodeType()== Node.ELEMENT_NODE) { System.out.println(childNodes.item(k).getNodeName() + ":" + childNodes.item(k).getTextContent()); } } System.out.println("=============="); } } catch (Exception e) { e.printStackTrace(); } } } 結果は次のとおりです。 id:1 name:张三gender:男age:26 ============== id:2 name:里斯gender:男age:36 ============== id:3 name:王五gender:女age:24 ============== 03. SAX分析SAX は Simple API for XML の略で、JDK によって提供される別の XML 解析方法です。 DOMと比較すると、SAXは解析ごとにXMLファイルのごく一部だけをメモリに読み込みます。大きなXMLファイルであっても、多くのメモリを必要とせず、メモリオーバーフローの問題もありません。 利点は次のとおりです。 - イベント駆動型モデルを使用してデータをセグメントごとに解析するため、メモリ使用量が少なくなります。
- データは読み取り時にのみチェックされ、メモリに保存する必要はありません。
- 効率とパフォーマンスが高く、システム メモリよりも大きなドキュメントを解析できます。
もちろん、欠点もあります。 - DOM パーサーと比較すると、SAX パーサーを使用して XML ファイルを読み取る場合の解析ロジックはより複雑になります。
- また、ドキュメント階層を見つけることができないため、同じドキュメントの異なる部分に同時にアクセスすることが困難になり、XPath もサポートされません。
実装プロセスは次のとおりです。 import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import java.io.InputStream; import java.util.List; import java.util.Map; public class SAXDemo { public static void main(String[] args) throws Exception { // 1.获取xml文件流InputStream inputStream = SAXDemo.class.getClassLoader().getResourceAsStream("demo.xml"); // 2.获取SAXParserFactory实例SAXParserFactory factory = SAXParserFactory.newInstance(); // 3.获取SAXparser实例SAXParser saxParser = factory.newSAXParser(); // 4.创建Handel对象SAXDemoHandel handel = new SAXDemoHandel(); // 5.解析XML文件saxParser.parse(inputStream, handel); // 6.获取读取结果List<Map<String, String>> students = handel.getStudents(); for (Map<String, String> student : students) { System.out.println(student.toString()); } } } import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class SAXDemoHandel extends DefaultHandler { private String value; private Map<String, String> student; private List<Map<String, String>> students = new ArrayList<>(); public List<Map<String, String>> getStudents() { return students; } /** * xml 解析开始* @throws SAXException */ @Override public void startDocument() throws SAXException { super.startDocument(); System.out.println("xml 解析开始"); } /** * xml 解析结束* @throws SAXException */ @Override public void endDocument() throws SAXException { super.endDocument(); System.out.println("xml 解析结束"); } /** * 解析XML 元素开始* @param uri * @param localName * @param qName * @param attributes * @throws SAXException */ @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { super.startElement(uri, localName, qName, attributes); System.out.println("开始遍历节点:" + qName); if (qName.equals("student")){ student = new HashMap<>(); for(int i=0; i<attributes.getLength();i++){ student.put(attributes.getQName(i), attributes.getValue(i)); } } } /** * 解析XML 元素结束* @param uri * @param localName * @param qName * @throws SAXException */ @Override public void endElement(String uri, String localName, String qName) throws SAXException { super.endElement(uri, localName, qName); System.out.println("节点遍历结束:" + qName); if(qName.equals("student")){ students.add(student); student = null; } else if(qName.equals("name") || qName.equals("gender") || qName.equals("age")){ student.put(qName, value); } } @Override public void characters(char[] ch, int start, int length) throws SAXException { super.characters(ch, start, length); // 获取节点值数组value = new String(ch,start,length).trim(); if (!value.equals("")) { System.out.println(value); } } } 結果は次のとおりです。 {gender=男, name=张三, id=1} {gender=男, name=里斯, id=2} {gender=女, name=王五, id=3} 04. JDOM解析JDOMは、Javaエコシステムにおける優れたオープンソースのXMLドキュメント解析ライブラリです。DOMとSAXを組み合わせたものと考えることができますが、実用的なアプリケーションにおけるDOMとSAXの欠点も解決しています。 利点は次のとおりです。 - ツリーベースのモデルは XML ファイルを処理し、データがメモリにロードされます。
- 下位互換性の制限がないため、DOM よりもシンプルです。
- 高速、欠陥が少ない
- SAX の分析機能を備えています。
- API は DOM よりも理解しやすいです。
もちろん、欠点もあります。 - メモリより大きい XML ドキュメントを処理できます。
- DOM 内の対応するトラバーサル パッケージはサポートされていません。
全体的に、JDOM は XML を使用する必要のあるほとんどのアプリケーションにとって依然として非常に便利です。 実装プロセスは次のとおりです。 <!--jdom --> <dependency> <groupId>org.jdom</groupId> <artifactId>jdom</artifactId> <version>1.1.3</version> </dependency> import org.jdom.Attribute; import org.jdom.Document; import org.jdom.Element; import org.jdom.input.SAXBuilder; import java.io.InputStream; import java.util.List; public class JdomDemo { public static void main(String[] args) throws Exception { // 1.获取xml文件流InputStream inputStream = JdomDemo.class.getClassLoader().getResourceAsStream("demo.xml"); // 2.创建SAXBuilder对象SAXBuilder saxBuilder = new SAXBuilder(); // 3.将输入流加载到build中Document document = saxBuilder.build(inputStream); // 4.获取根节点Element rootElement = document.getRootElement(); // 5.获取子节点List<Element> children = rootElement.getChildren(); for (Element child : children) { List<Attribute> attributes = child.getAttributes(); // 遍历标签属性for (Attribute attr : attributes) { System.out.println(attr.getName()+":"+attr.getValue()); } // 遍历标签子节点List<Element> childrenList = child.getChildren(); for (Element o: childrenList) { System.out.println(o.getName() + ":" + o.getValue()); } System.out.println("=============="); } } } 結果は次のとおりです。 id:1 name:张三gender:男age:26 ============== id:2 name:里斯gender:男age:36 ============== id:3 name:王五gender:女age:24 ============== 05. DOM4J 解析DOM4J も、Java エコシステムにおける優れたオープンソース XML ドキュメント解析ライブラリであり、JDOM のアップグレードです。 当初は JDOM のフォークでしたが、後に基本的な XML ドキュメント表現を超えた多くの機能が組み込まれ、最終的にスタンドアロン ツールとしてリリースされました。 利点は次のとおりです。 - 優れたパフォーマンス、強力な機能、そして非常に使いやすい
- 開発が簡単で、パフォーマンスを向上させるためのいくつかの代替方法も提供します。
- XPathをサポート
唯一の欠点: 実装プロセスは次のとおりです。 <!-- dom4j --> <dependency> <groupId>dom4j</groupId> <artifactId>dom4j</artifactId> <version>1.6.1</version> </dependency> public class Dom4jDemo { public static void main(String[] args) throws Exception { // 1.获取xml文件流InputStream inputStream = Dom4jDemo.class.getClassLoader().getResourceAsStream("demo.xml"); // 2.创建Reader对象SAXReader reader = new SAXReader(); // 3.加载xml Document document = reader.read(inputStream); // 4.获取根节点Element rootElement = document.getRootElement(); // 5.遍历元素Iterator iterator = rootElement.elementIterator(); while (iterator.hasNext()){ Element stu = (Element) iterator.next(); // 遍历标签属性List<Attribute> attributes = stu.attributes(); for (Attribute attribute : attributes) { System.out.println(attribute.getName() + ":" + attribute.getValue()); } // 遍历标签子节点Iterator iterator1 = stu.elementIterator(); while (iterator1.hasNext()){ Element stuChild = (Element) iterator1.next(); System.out.println(stuChild.getName()+":"+stuChild.getStringValue()); } System.out.println("=============="); } } } 結果は次のとおりです。 id:1 name:张三gender:男age:26 ============== id:2 name:里斯gender:男age:36 ============== id:3 name:王五gender:女age:24 ============== 06. 要約結論として、DOM4Jは多くのオープンソースプロジェクトで広く使用されています。例えば、HibernateフレームワークはXML設定ファイルの読み取りにDOM4Jを使用しており、SunのJAXMもDOM4Jを使用しています。 したがって、XML 解析ツールを使用する必要があり、プロジェクトに他の制約がない場合は、DOM4J が推奨される選択肢です。 プロジェクトで既に使用されているXML解析ツールの中には、移植性の問題が懸念されない場合、DOM4Jに置き換えることができるものもあります。もちろん、個々のケースを個別に分析する必要があります。移行コストが非常に高く、古いツールがまだ正常に動作する場合は、移行する必要はありません。つまり、最も適切な選択肢が最善です。移行の価値があるかどうかは、リソースコスト、時間、そして必要性を評価する必要があります。 |