今回はアプリ開発関連というよりは純粋にJavaのお話です。
なんだか仕事で「JavaでXMLの操作」をしないといけなさそうだったので、休日を利用していろいろと調べました。
ライブラリはいろいろとあるみたいだけど、「dom4j」を使うのが簡単みたい。
ということで、以下は調べたことのメモとなります。
dom4jをプロジェクトに入れる
とりあえず、以下からdom4jをダウンロードします。
http://sourceforge.net/projects/dom4j/files/dom4j/
Eclipseで使う場合は、Javaのビルドパスに適当にJarファイルを追加します。
とりあえずは、入ってたのを全部いれました。
基本の使い方
「dom4j」には主に「Document」「Element」「Node」というオブジェクトが存在してるっぽい。
結構そのまんまだからわかりやすいですね。
- Document ーーXML全体
- Element ーーNode、Elementが入った要素の集合体(単体でも使える)
- Node ーーXMLの単体の要素(かな?)
すみません、上はあんまり調べてないからもしかしたらちょっと違うかもです。
違うよって場合ご指摘ください。
Step1. XMLを読み込む
以下のようにしたらXMLを読み込めるみたい。
SAXReader reader = new SAXReader(); try { Document doc = reader.read("/tmp/test.xml"); } catch (DocumentException e) { //例外処理 }
簡単ですね。そのあと、このDocumentの中からElementやらを取り出すことで、XMLの中身を読み込むことができます。
Step2. XMLの要素を読み込む
読み込み方にはいくつかあるみたいですが、とりあえず2つの方法を紹介。
あ、ちなみにXMLファイルは以下のものを読むことにします。
<persons> <person> <name>Branch</name> <job>Programmer</job> </person> <person> <name>CookieMonster</name> <job>Monster</job> </person> <person> <name>Crunky</name> <job>Chocolate</job> </person> </persons>
// ①ルート要素からひとつずつとっていく Element root = doc.getRootElement(); for (Iterator i = root.elementIterator(); i.hasNext();) { Element elem = (Element) i.next(); Element elem2 = elem.element("job"); System.out.println(elem2.getStringValue()); } // ②XPathを使って一致するNodeをとってくる List nodes = doc.selectNodes("//job"); for (Iterator i = nodes.iterator(); i.hasNext();) { Node n = (Node) i.next(); System.out.println(n.getText()); }
①も②も、以下のようなのが出力されます。
Programmer Monstar Chocolate
①の解説
1. まず、doc.getRootElement();の箇所で、最初の要素(この場合はpersons)を参照します。
2. その>persons<エレメントの中には、>person<が3つ存在しています。
3. それをイテレータでぐるぐる回し、それぞれの「job」要素を参照しています。
②の解説
1. XPathを使い、ダイレクトに「job」要素をとってきます。
2. イテレータでぐるぐる回して、それぞれのテキストをとってきています。
簡単ですね。
ちなみにXPathとは、そういうXMLのセレクタ方式があるらしく、その名称です。
XPathはこちらに詳しくのってました。
http://gogodiet.net/z/xml/7.htm
Step3.書き込みを行う
書き込みについては、こちらを参考にしました。
Java開発 dom4j – XMLをファイルに出力する
http://java6.blog117.fc2.com/blog-entry-19.html
Document newDoc = DocumentHelper.createDocument(); Element newRoot = newDoc.addElement("root"); Element newPerson = newRoot.addElement("person"); // エレメントを作成して追加する Element addName = DocumentHelper.createElement("newName"); addName.setText("newNameText"); newPerson.addElement(addName); // メソッドチェーンで追加する newPerson.addElement("newJob").setText("jobs"); // ファイルに出力 FileOutputStream fos = null; OutputFormat format = new OutputFormat("t", true, "UTF-8"); XMLWriter writer = null; try { fos = new FileOutputStream("/パス.xml"); writer = new XMLWriter(fos, format); writer.write(newDoc); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { writer.close(); } catch (IOException e) { e.printStackTrace(); } }
実行すると、以下のようなXMLファイルが出力されます。
<root> <person> <newName>newNameText</newName> <newJob>jobs</newJob> </person> </root>
今回検証したソース
最後に、今回実際に使ってみた際に作成したソースです。
テキトーに作ったのでかなりアレですけど、/tmp直下に上と同じXMLがあれば動くかと。
package jp.brbranch.work; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.Iterator; import java.util.List; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.dom4j.Node; import org.dom4j.io.OutputFormat; import org.dom4j.io.SAXReader; import org.dom4j.io.XMLWriter; public class XmlSample { private final File file; public XmlSample(String path) { file = new File(path); } public void read(String elemName) { if (file.exists() == false) return; SAXReader reader = new SAXReader(); try { Document doc = reader.read(file); Element root = doc.getRootElement(); for (Iterator i = root.elementIterator(); i.hasNext();) { Element elem = (Element) i.next(); Element elem2 = elem.element(elemName); System.out.println(elem2.getStringValue()); } } catch (DocumentException e) { e.printStackTrace(); } } public void readNode(String node) { if (file.exists() == false) { return; } SAXReader reader = new SAXReader(); try { Document doc = reader.read(file); List nodes = doc.selectNodes(node); for (Iterator i = nodes.iterator(); i.hasNext();) { Node n = (Node) i.next(); System.out.println(n.getText()); } } catch (DocumentException e) { e.printStackTrace(); } } public void write(String newName) throws DocumentException { if (file.exists() == false) { return; } SAXReader reader = new SAXReader(); Document doc = reader.read(file); Document newDoc = DocumentHelper.createDocument(); Element newRoot = newDoc.addElement("root"); Element root = doc.getRootElement(); for (Iterator i = root.elementIterator(); i.hasNext();) { Element elem = (Element) i.next(); Element newPerson = newRoot.addElement(elem.getName()); // エレメントを作って追加する Element name = elem.element("name"); Element addName = DocumentHelper.createElement("newName"); addName.setText(name == null ? "" : name.getText()); newPerson.add(addName); // メソッドチェーンで追加する Element job = elem.element("job"); newPerson.addElement("newJob").setText( job == null ? "" : job.getText()); } FileOutputStream fos = null; OutputFormat format = new OutputFormat("t", true, "UTF-8"); XMLWriter writer = null; try { fos = new FileOutputStream(newName); writer = new XMLWriter(fos, format); writer.write(newDoc); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { writer.close(); } catch (IOException e) { e.printStackTrace(); } } } public static void main(String[] arg) { System.out.println("開始"); XmlSample sample = new XmlSample("/tmp/test.xml"); System.out.println("各ルート直下後の要素のjobを読み込みます"); sample.read("job"); System.out.println("各要素のnameを読み込みます"); sample.readNode("//name"); System.out.println("新しいXMLファイルを作成します"); try { sample.write("/tmp/test2.xml"); } catch (DocumentException e) { e.printStackTrace(); } System.out.println("終了"); } }