XMLの半構造化データについての一般的な議論
scalaでXMLをどうやって扱うかの重要な部分の概要説明
XMLリテラルを用いたノードの作成。
XMLファイルの保存と読み込み。
queryとpattern matchingを使ったノードの分離。
26.1 Semi-structured data
XMLは半構造化された形式を取っている。
ツリー構造になっていてplain textよりは構造化されている。
プログラム言語のオブジェクトよりは構造化されていない。
タグ間はフリーフォーマット。
型システムもない。
半構造化はプログラムでデータをシリアライズする時に非常に有用
ネットワーク経由で送信したり、ディスクに保存する場合。
構造化されているデータ全てをバイナリにする代わりに使える。
まずは半構造化フォーマットに変換する。
その後に半構造化フォーマットに元々準備されているライブラリで
半構造化フォーマットは色々あるがInternetではXMLが
ほとんどのOSのほとんどの言語にXMLライブラリが存在する。
ネットワーク外部性により益々使われる様になっている。
Internet経由でのやり取りをする場合はXMLを避けて通
scalaでもXMLの特別なサポートを行っている。
本章で標準的なメソッドやpattern matchingによる処理を紹介。
さらに良く使われるidiomも紹介する。
26.2 XML overview
tagとtextで構成される。
textは任意
tagは<tag></tag>
tagはstart<tag>とend</tag>
<tag/>: startとendを合わせた表現
<tag attr="3">: start tagには属性をつけられる
26.3 XML literals
scalaではどこにでもXMLのリテラルを記載する事が出来る
単にstart tagで書き始めればend tagまでXMLリテラルと認識される。
scala> <a>
This is some XML.
Here is a tag: <atag/>
</a>
res0: scala.xml.Elem = ...
Type Elem: XML element
Class Node: 全てのXML node classの上位の抽象クラス
Class Text: testのみを保持しているXMLのnode。<a>
Class NodeSeq: XML nodeのsequence
XMLのライブラリはNodeSeqを処理する様に作られている
Nodeは単一NodeのみのNodeSeqとして定義されてい
NodeSeqに対する処理は単一Nodeに対しても行える。
XMLの内部にも{}を使ってscalaコードを埋め込める。
scala> <a> {"hello"+", world"} </a>
res1: scala.xml.Elem = <a> hello, world </a>
任意のscalaコードを書けるので、
scalaコードの評価結果が埋め込まれてXMLになる。
空のXMLを表現したい場合はxml.NodeSeq.
評価結果がXML nodeでない場合は、
text中の<、>、&はURL encodeされる。
XMLのtagと同様のstringをつあってもtextとして
tagとして認識させたい場合はXMLリテラルかXMLのtyp
26.4 Serialization
XMLリテラルとbraceによるscalaコードの埋め込みで
下記がシリアル化(XML化)の例
abstract class C {
val s: String;
val i: Int;
def toXML =
<c>
<s>{s}</s>
<i>{i}</i>
</c>
}
下記の様に実行できる。
scala> val c = new C {
val s = "hoge"
val i = 10
}
scala> c.toXML
abstractクラスでもanonymous classを使ってnewできる。
{}をtextとして使いたい場合は{{、}}を使う。
26.5 Taking XML apart
多数あるXMLライブラリのメソッドの中で特に良く使うのは3つ
XMLを分解するためのメソッド。
XPath言語に基づいている。
外部ツールを呼び出すことなく直接scalaから使える。
Extracting text
textメソッドを使うと全要素のtext部分が一つのstri
scala> <a>Sounds <tag/> good</a>.text
res8: String = Sounds good
URL encodeされている場合は自動的にdecodeされる。
Extracting sub-elements
\"tag"メソッドを使うとタグが"tag"
scala> <a><b><c>hello</c></b></a> \"b"
res10: scala.xml.NodeSeq = <b><c>hello</c></b>
\\"tag"メソッドを使うとツリー全体を検索して(deep search)要素を取り出す。
topレベル要素も含めて全体が検索される。
\、\\はXPathの/、//に対応している。
scalaでは/、//を別の意味で使うので\、\\とした。
Extracting attributes
\"@attr"、\\"@attr"
26.6 Deserialization
textメソッドを使えばシリアル化してXMLにしたオブジェク
def fromXML(node: scala.xml.Node): C =
new C {
val s = (node \"s").text
val i = (node \"i").text.toInt
}
** 実際に定義する時はclass Cのcompanion objectに定義すると良さそう。
26.7 Loading and saving
toStringを使うだけでもXMLをStringにすること
ライブラリの関数を使った方がより良い。
encode情報等のdirectiveをつける事が出来るため
XML.saveFull(ファイル名, XMLノード, エンコード, エンコードフラグ, ドキュメントタイプ)
scala.xml.XML.saveFull("
エンコードフラグはencode declarationをつけるかどうか。
ドキュメントタイプは説明省略。
XML.loadFile(ファイル名)
scala> val loadnode = xml.XML.loadFile("therm1.xml")
26.8 Pattern matching on XML
XML pattern
XMLリテラルと同様の形式。
{}の内側はscalaのpattern matchingのパターンになる。
変数束縛、型テスト、ワイルドカード(_、_*)
(node :scala.xml.Node) match { case <a>{contents}</a> => ... }
「single sub-node」のみmatchする。
子要素が一つの場合。
<a>hoge</a>にはmatchする。
孫要素があってもOK.
<a><b>hoge</b></a>にはmatchする。
子要素が複数ならmatchしない。
<a><b>hoge</b><b>fuga</b></a>
(node :scala.xml.Node) match { case <a>{contents @ _*}</a> => contents }
子要素が複数の場合は_*
<a><b>hoge</b><b>fuga</b></a>
Seq[scala.xml.Node] = ArrayBuffer(<b>hoge</b>, <b>fuga</b>)
空白文字
XMLリテラルを使うときに空白文字に注意する。
タグ間の改行やタブ等もXMLのtextと要素として認識される
下記だと<a>の子要素として<b>と<c>と</a>
<a>
<b>hoge</b>
<c>fuga</c>
</a>
26.9 Conclusion
scalaではXMLの特別なサポートとしてXMLリテラルがプ
他にも沢山の拡張、ライブラリ、ツールがある。
scala向けにカスタマイズされたもの
Java向けだがsalaでもつかえるもの
言語非依存のもの
0 件のコメント:
コメントを投稿