こんにちは、キャスレーコンサルティングのSD(システム・デザイン)部ヤマナです。
今回はjOOXというjavaのライブラリを紹介させて頂きます。
jQueryライクなAPIでXMLの読取り/書込みが可能です。
今回は以下の操作についてjOOXのサンプルソースをご紹介します。
- ファイル読取
- Webからの読取
- ゼロから作成
- 既存XMLの変更
ファイル読取
まずは読取りの例から。
以下の様なファイルを対象とする場合。
<?xml version="1.0"?> <parent> <children> <child id="elder"><age>10</age><name>taro</name><gender>male</gender></child> <child id="younger"><age>6</age><name>jiro</name><gender>male</gender></child> </children> </parent>
以下の様に、jQueryのセレクタと同様コードでIDによる抽出が可能です。
import static org.joox.JOOX.$; import org.joox.Match; Match fromFile = $(new File("sample.xml")); Match younger = fromFile.find("#younger"); System.out.println( younger.child("name").text() ); // ===> jiro System.out.println( younger.child("age").text() ); // ===> 6
Matchオブジェクトは、jQueryオブジェクトのようなものです。
内部的にxmlの要素(のリスト)を保持しています。
jQeuryオブジェクトと同様に、textメソッドによる子要素の入出力やfind,filter,childメソッドによる更なる絞り込みが可能です。
Webからの読取
また、取得元としてURLを指定することも可能です。
maven centralのpomを対象として、dependencyをgradleの形式に変換する例がこちらです。
import java.net.URL; Match pom = $(new URL("http://central.maven.org/maven2/org/springframework/spring-core/4.2.5.RELEASE/spring-core-4.2.5.RELEASE.pom")); List<String> dependencies = pom.find("dependency").each().stream() .map( d -> d.find("groupId").text() + ":" + d.find("artifactId").text() + ":" + d.find("version").text()) .collect(Collectors.toList()); System.out.println(dependencies);
MatchオブジェクトはjQueryオブジェクト同様に、内部的に要素のリストを保持しています。
これを取り出すのがMatch#eachメソッドで、上記の例ではその結果からさらにjava8のstreamメソッドを呼び出してリストへの変換を行っています。
結果は以下のようになります。
[commons-codec:commons-codec:1.10, commons-logging:commons-logging:1.2, log4j:log4j:1.2.17, net.sf.jopt-simple:jopt-simple:4.9, org.aspectj:aspectjweaver:1.8.8]
さて、次はXMLを作成する例です。
ゼロから作成
import static org.joox.JOOX.$; import org.joox.Match; Match parent1 = $("parent").append( $("child").append($("number").text("8.1")) .append($("string").text("ON")) ); System.out.println(parent);
出力結果(XMLは整形しています)
<parent> <child> <number>8.1</number> <string>ON</string> </child> </parent>
これだけでも十分スッキリとかけていますが、さらに短縮が可能です。
まず、上記の例では以下の様な処理を行っています。
- “$”メソッドにタグ名を渡す事で要素”parent”, “child”のインスタンスを生成
- number, string要素のインスタンスのtextメソッドでテキストノードを追加(textメソッドはインスタンスをそのまま返します)
- 要素”child”にnumber, string要素を追加
- parent要素にそのchild要素を追加
“$”メソッドには以下のオーバーロードがあるため、
$(String name, String content)
こう書けます。
$("parent").append( $("child").append( $("number", "8.1"), $("string", "ON") ))
さらに、以下のオーバーロードも存在するため、
$(String name, Match ... content)
こう書けます。
$("parent", $("child", $("number", "8.1"), $("string", "ON") ))
非常にスッキリとしました。
既存XMLの変更
既存XMLは以下のものとします。
<?xml version="1.0"?> <parent> <children> <child id="elder"><age>10</age><name>taro</name><gender>male</gender></child> <child id="younger"><age>6</age><name>jiro</name><gender>male</gender></child> </children> </parent>
コードは以下の通り。
Match fromFile = $(new File("sample.xml")); // $メソッドでPOJOをXML化も可能 fromFile.find("children").append( $(new Child("hanako", 1, "female")).attr("id", "sister") ); // gender要素のテキストが'male'のみの'child'要素を抽出 Match bros = fromFile.find("child").filter( c -> $(c).child("gender").text().equals("male") ); bros.each().stream().forEach( b -> b.find("age").text( String.valueOf(Integer.valueOf(b.find("age").text()) + 2)) ); System.out.println(fromFile);
出力結果(XMLは整形しています)
<parent> <children> <child id="elder"><age>12</age><name>taro</name><gender>male</gender></child> <child id="younger"><age>8</age><name>jiro</name><gender>male</gender></child> <child id="sister"><age>1</age><gender>female</gender><name>hanako</name></child> </children> </parent>
上記の例では、前述のXMLファイルに対し、以下の様な操作を行っています。
- name=”hanako”, age=1, gender=”female”というフィールドを持つChildオブジェクトを$メソッドによりElementに変換し、childerenに追加
(この時のタグ名は、クラス名を小文字にしたものになるようです) - 追加後のchild要素のうち、gender=”male”という子要素を持つ物を抽出
- 上記抽出結果の全てに対し、age=age+2を設定
複雑な条件の抽出の場合、filterメソッドやfindメソッドにorg.joox.Filterインターフェースを実装したオブジェクトを渡す必要があるのですが、
booleanを返すメソッドを1つだけ持つインターフェースのため、java8との相性も良いのではないかと思います。
さいごに
先日実務にて、XMLを入力として受け取るような帳票エンジンを使用した際にjOOXを使用したため、簡単にご紹介させていただきました。
JSONに押され、以前に比べると使用頻度の下がったXMLですが、たまに使うこともあると思います。
java標準APIでは要素の取得にxpathを使う必要があるなど、苦しい部分もjOOXで緩和出来る場面もあるのではないでしょうか。
なお、今回のサンプルコードおよびgradleのファイルは以下に共有しています。
https://github.com/yohei224/joox_example
宜しければご覧になってみてください。