8.
XML
8.1.
生成
Scala原生支持xml,就如同Java支持String一样,这就让生成xml和xhtml很简单优雅:
val name = "james"
val age = 10
val html = <html>name={name}, age="{age}"</html> toString
// <html>name=james, age="10"</html>
又如:
val html = <html><head><title>{myTitle}</title></head><body>{"hello world"}</body></html>
更复杂的例子:
val x = <r>{(1 to 5).map(i => <e>{i}</e>)}</r>
// <r><e>1</e><e>2</e><e>3</e><e>4</e><e>5</e></r>
val x0 = <users><user name="qh"/></users>
val <users>{u}</users> = x0 // u: scala.xml.Node = <user name="qh"></user>
By the way, if you want to include a curly brace (`{‘ or `}‘) as XML text, as opposed to using them to escape to Scala code, simply write two curly braces in
a row:
scala> <a> {{{{brace yourself!}}}} </a> res1: scala.xml.Elem = <a> {{brace yourself!}} </a>
8.2.
xml文件
xml.XML loadString "<p></p>"
xml.XML loadFile "abc.xml"
xml.XML.saveFull("foo.xml", node, "UTF-8", xmlDecl: Boolean, doctype : DocType)
8.3.
读取:
val x = <r>{(1 to 5).map(i => <e>{i}</e>)}</r>
// <r><e>1</e><e>2</e><e>3</e><e>4</e><e>5</e></r>
(x \ "e") map (_.text.toInt) // List(1, 2, 3, 4, 5)
val x0 = <users>
<user name="qh"><age>20</age></user>
<user name="james"><age>30</age></user>
</users>
(x0 \ "user") // <user name="qh"><age>20</age></user>, <user name="james"><age>30</age></user>)
(x0 \ "user" \ "age") // (<age>20</age>, <age>30</age>)
(x0 \ "age") // 直接下级: ()
(x0 \\ "age") // 所有下级:(<age>20</age>, <age>30</age>)
(x0 \ "_") 所有
8.4
访问属性
val x = <uu><u name="qh" /><u name="james" /><u name="qiu" /></uu>
scala> (x \ "u" \\ "@name") foreach println
qh
james
qiu
例子:
val data =
<shopping>
<item name="bread" quantity="3" price="2.50"/>
<item name="milk" quantity="2" price="3.50"/>
< /shopping>
val res = for (item <- data \ "item" ;
price = (item \ "@price").text.toDouble ;
qty = (item \ "@quantity").text.toInt)
yield (price * qty)
printf("$%.2f\n", res.sum)
8.5
Deserialization
You can write of a serializer, a parser from XML back into your internal data structures. For example, you can parse back a CCTherm instance by using the following code:
def fromXML(node: scala.xml.Node): CCTherm =
new CCTherm {
val description = (node \ "description").text
val yearMade = (node \ "yearMade").text.toInt
val dateObtained = (node \ "dateObtained").text
val bookPrice = (node \ "bookPrice").text.toInt
val purchasePrice = (node \ "purchasePrice").text.toInt
val condition = (node \ "condition").text.toInt
}
This code searches through an input XML node, named node, to find each of the six pieces of data needed to specify a CCTherm. The data that is text is extracted with .text and left as is.
8.6
格式化输出
val pp = new xml.PrettyPrinter(80, 4) // 行宽 80,缩进为 4
pp formatNodes <b><a/></b>
结果是字符串
<b>
<a></a>
</b>
8.7
Pattern
matching on XML
A pattern embedded in {} can use the full Scala pattern language, including binding new variables, performing type tests, and ignoring content using the _ and _* patterns. Here is a simple example:
def proc(node: scala.xml.Node): String =
node match {
case <a>{contents}</a> => "It‘s an a: "+ contents
case <b>{contents}</b> => "It‘s a b: "+ contents
case _ => "It‘s something else."
}
scala> proc(<a>apple</a>)
res16: String = It‘s an a: apple
scala> proc(<b>banana</b>)
res17: String = It‘s a b: banana
scala> proc(<c>cherry</c>)
res18: String = It‘s something else.
val catalog =
<catalog>
<cctherm>
<description>hot dog #5</description>
<yearMade>1952</yearMade>
<dateObtained>March 14, 2006</dateObtained>
<bookPrice>2199</bookPrice>
<purchasePrice>500</purchasePrice>
<condition>9</condition>
</cctherm>
<cctherm>
<description>Sprite Boy</description>
<yearMade>1964</yearMade>
<dateObtained>April 28, 2003</dateObtained>
<bookPrice>1695</bookPrice>
<purchasePrice>595</purchasePrice>
<condition>5</condition>
</cctherm>
</catalog>
catalog match {
case <catalog>{therms @ _*}</catalog> =>
for (therm @ <cctherm>{_*}</cctherm> <therms)
println("processing: "+(therm \ "description").text)
}
processing: hot dog #5
processing: Sprite Boy