首页 > 代码库 > Scala的XML操作

Scala的XML操作



8.  XML

8.1.     生成

Scala原生支持xml,就如同Java支持String一样,这就让生成xmlxhtml很简单优雅:

val name = "james"

val age = 10

val html = <html>name={name}, age="{age}"</html> toString

// <html>name=james, age=&quot;10&quot;</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 =http://www.mamicode.com/

<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

Scala的XML操作