JavaでXmlを操作する(Dom4j)

Pocket

java_tit_03

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

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です