今回はアプリ開発関連というよりは純粋に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("終了");
}
}
