scala 內建了 scala.xml 可以處理 XML,以下我們簡單測試了一下 xml 的功能,目前看起來,標準函式庫的功能就足夠應用的需求了。
產生及使用 scala.xml
scala 可以直接偵測 < 這個符號,並以 xml 的方式處理,在程式中,直接把 xml指定給變數,就會直接產生 xml 物件。
scala> val xml = <store><item type="book">Novel</item><item type="pen">pencil</item></store>
xml: scala.xml.Elem = <store><item type="book">Novel</item><item type="pen">pencil</item></store>
產生 xml 物件後,可以用 text method,將所有欄位的 value 全部印出來
scala> xml.text
res0: String = Novelpencil
用 XPath 的語法,可以取得子節點的內容
scala> xml\"item"
res1: scala.xml.NodeSeq = NodeSeq(<item type="book">Novel</item>, <item type="pen">pencil</item>)
scala> (xml\"item").map(_.text).mkString(" ")
res2: String = Novel pencil
用 "@type" selector,可以取得所有 type 屬性的值
scala> (xml\"item").map(_\"@type")
res3: scala.collection.immutable.Seq[scala.xml.NodeSeq] = List(book, pen)
"@type" 只能取得目前這個節點的 children,如果要將所有出現同樣屬性的節點都取出來,就要用 "\" selector
scala> znodes\"z"
res5: scala.xml.NodeSeq = NodeSeq(<z x="1"/>)
scala> znodes\\"z"
res6: scala.xml.NodeSeq = NodeSeq(<z x="1"/>, <z x="2"/>, <z x="3"/>, <z x="4"/>)
跟剛剛一樣的方法,就可以找到屬性 x 的所有 values
scala> (znodes\\"z").map(_\"@x")
res12: scala.collection.immutable.Seq[scala.xml.NodeSeq] = List(1, 2, 3, 4)
如果是一個 xml string,可以用 scala.xml.XML.loadString 將 string 轉換為 xml。
scala> val xmlstring = """<store><item type="book">Novel</item><item type="pen">pencil</item></store>"""
xmlstring: String = <store><item type="book">Novel</item><item type="pen">pencil</item></store>
scala> val xmlfromstring = scala.xml.XML.loadString(xmlstring)
xml: scala.xml.Elem = <store><item type="book">Novel</item><item type="pen">pencil</item></store>
scala> xml == xmlfromstring
res13: Boolean = true
manual Serializing and Deserializing xml
首先定義 Stock class,在 toXml method 中,可以直接用 {symbol} 將 Stock 物件中的資料,產生到 xml 中,而 fromXml 就是用剛剛的 text 的方式取得 xml 裡面的資料放入 Stock 物件中。
case class Stock(var symbol: String, var businessName: String, var price: Double) {
// convert Stock fields to XML
def toXml = {
<stock>
<symbol>{symbol}</symbol>
<businessName>{businessName}</businessName>
<price>{price}</price>
</stock>
}
override def toString =
s"symbol: $symbol, businessName: $businessName, price: $price"
}
object Stock {
// convert XML to a Stock
def fromXml(node: scala.xml.Node):Stock = {
val symbol = (node \ "symbol").text
val businessName = (node \ "businessName").text
val price = (node \ "price").text.toDouble
new Stock(symbol, businessName, price)
}
}
用個簡單的 TestXml 測試 toXml 及 fromXml
object TestXml extends App {
// convert a Stock to its XML representation
val aapl = new Stock("AAPL", "Apple", 600d)
println(aapl.toXml)
// convert an XML representation to a Stock
val googXml = <stock>
<symbol>GOOG</symbol>
<businessName>Google</businessName>
<price>620.00</price>
</stock>
val goog = Stock.fromXml(googXml)
println(goog)
}
執行結果如下
<stock>
<symbol>AAPL</symbol>
<businessName>Apple</businessName>
<price>600.0</price>
</stock>
symbol: GOOG, businessName: Google, price: 620.0
References
Basic XML processing with Scala
Practical Scala – processing XML
Serializing and deserializing XML in Scala
Generating dynamic XML from Scala source code (like a template)
沒有留言:
張貼留言