scala.xml の代替を目指しているライブラリなので使い勝手は似ているが、SelectorやZipperなど、scala.xmlには無い機能がある。
基本
com.codecommit.antixml._ をインポートすると、scala.xmlのクラスをantixmlのクラスに置き換えることができる。
import com.codecommit.antixml._ // scala.xml.Elem を com.codecommit.antixml.Elem に変換 val xml =Stay hungry, don't eat. .convert // ドキュメントではconvertメソッドではなく、 // antiメソッドを読んでいるのだが見つからない。。 // Text, Groupなどはcom.codecommit.antixml のクラスに上書きされてる。 val textGroup = Group(Text("stealth marketing"))
Selector
SelectorはPartialFunctionを継承していて、ノードをマッチさせるために使うのだが、任意の戻り値に変換できる。StringとSymbolはSelector[Elem]に暗黙変換される。
val text: Selector[String] = Selector({ case Text(str) => str }) // Vector[String]が返ってくる。 xml \ text // => Vector[String] // Selector[Elem]の場合はZipper[Elem]が返ってくる。 xml \ "string" // => Zipper[Elem] xml \ 'symbol // => Zipper[Elem]
Zipper
ZipperはXMLツリーをimmutableに更新する機能。ノードを探索して取得したZipperを書き換えた後に、unselectメソッドを呼ぶと更新されたXML全体が取得できる。
val xml =.convert val updatedXml = (xml \ 'ceo).updated(0, Carol Bartz Scott Thompson .convert).unselect // =>Scott Thompson
探索したあとのノードから親ノードを再構成できるのは割とうれしい。でもscala.xml使うよりはXMLの更新が楽にはなっているが、まだちょっと面倒。使い方が悪いのかもしれないから今後調べる必要がある。
ちなみに xml \ 'hoge \ 'fuga のように2段階で探索した場合は、unselectを2回呼ぶ必要がある。
一応gistに上げといた↓
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env scalas | |
!# | |
/*** | |
scalaVersion := "2.9.0-1" | |
libraryDependencies ++= Seq( | |
"com.codecommit" %% "anti-xml" % "0.3" | |
) | |
*/ | |
import com.codecommit.antixml._ | |
val movie = | |
<movie> | |
<title>Mulholland Drive</title> | |
<director>Unkown</director> | |
<actors> | |
<actor>Naomi Watts</actor> | |
<actor>Laura Harring</actor> | |
</actors> | |
</movie>.convert // convert scala.xml.Elem to com.codecommit.antixml.Elem | |
// create Selector | |
val text = Selector({ | |
case Text(str) => str | |
}) | |
// apply Selector | |
val actorNames = movie \ 'actors \ 'actor \ text | |
println(actorNames) // => Vector(Naomi Watts, Laura Harring) | |
// select director as zipper | |
val zipper:Zipper[Elem] = movie \ 'director | |
// update <director>'s text. | |
val crrectDirector:Elem = zipper.head.copy(children=Group(Text("David Lynch"))) | |
// replace <director> | |
val updatedZipper = zipper.updated(0, crrectDirector) | |
// rebuild xml by updated zipper | |
val updatedXml = updatedZipper.unselect | |
// <director>Unkown</director> is replaced with <director>David Lynch</director> | |
println(updatedXml) |