Scala入门到精通——第二十七节 Scala操纵XML
本節主要內容
1. XML 字面量
XML是一種非常重要的半結構化數據表示方式,目前大量的應用依賴于XML,這些應用或利用XML作為數據交換格式,或利用XML進行文件配置等。像Java、C++及其它流行的程序開發語言都是依賴于第三方庫來實現XML的操作,例如JAVA經常通過JDOM,DOM4J等XML處理工具進行XML的操縱,但Scala提供了對XML的原生支持,通過scala.xml._包下的類或對象可以進行任何的XML操作。下面的代碼演示了Scala中如何定義XML字面量。
scala> var x: scala.xml.Elem = <site><name>xuetuwuyou</name><url>http://www.xuet uwuyou.com/</url></site> x: scala.xml.Elem = <site><name>xuetuwuyou</name><url>http://www.xuetuwuyou.com/ </url></site>scala> <site><name>xuetuwuyou</name><url>http://www.xuetuwuyou.com/</url></site>res8: scala.xml.Elem = <site><name>xuetuwuyou</name><url>http://www.xuetuwuyou.c om/</url></site>通過上面的代碼不難發現,scala會自動地對XML進行解析,并識別為scala.xml.Elem類型。scala中與XML相關的包和類很多,具體如下圖所示:
在深入講解Scala操縱XML之前,先對幾個主要的術語進行介紹:
圖中描述了屬性、根元素、子元素、元素及文本的概念及它們之間的關聯關系,所有的文本、元素被統稱為節點(Node)。下面給出的scala XML中的幾個重要的類:
- Node類。它的一個抽象類,用于對象XML中的所有節點進行抽象:
- Text類,僅包含文本的節點,例如<url>http://www.xuetuwuyou.com/</url> 中的http://www.xuetuwuyou.com/就是一種Text對象
- NodeSeq類,它同樣是一個抽象類,指的是節點的序列,Node繼承自NodeSeq,可以看Node可作是NodeSeq只有一個元素的情況。
scala中的XML中可以執行scala表達式,例如
val s="http://www.xuetuwuyou.com/"val xmlUrl= <a>{" "+s+" "}</a>//<a> http://www.xuetuwuyou.com/ </a>println(xmlUrl)val age=30val xml1= if(age<29) <age> {age} </age> else NodeSeq.Empty//<age> 28 </ageprintln(xml1)//<age> 79 </age>val xml2= <age> {29+50} </age>println(xml2)2. XML內容提取
提取XML中的文本:
object ExtractXMLText extends App{val x= <person><name>搖擺少年夢</name><age>27</age></person>//搖擺少年夢27println(x.text) }這種提取方式將XML中所有的文本內容提取出來并拼接在一起,在實際中我們可能需要精確提取,比如我只想提取name元素中的內容,此時可以采用下列方式:
val x= <person><name>搖擺少年夢</name><age>27</age></person> //提取name子結點,類型XPATH訪問方式 //<name>搖擺少年夢</name>println(x \ "name") //<name>搖擺少年夢</name> //提取name中的文本println((x \ "name").text) //搖擺少年夢scala> x \ "age" res2: scala.xml.NodeSeq = NodeSeq(<age>27</age>)x \ “age” 這種子元素的提取方式,返回的類型是scala.xml.NodeSeq
\的方式只能提取子元素,不能提取子元素的子元素,例如:
val x= <persons><person><name>搖擺少年夢</name><age>27</age></person><person><name>張三</name><age>29</age></person><person><name>李四</name><age>30</age></person></persons>//返回空NodeSeqprintln(x \ "name")// \\提取二級子元素//<name>搖擺少年夢</name><name>張三</name><name>李四</name>println(x \\ "name")通過\和\\可以提取任何XML的子元素及其文本內容,但如果XML元素帶有屬性,那又如何提取呢?
val x= <persons><person name="搖擺少年夢" age="27" /><person><name>張三</name><age>29</age></person><person><name>李四</name><age>30</age></person></persons>//用@方式提取name屬性//搖擺少年夢println(x \\ "@name")3. XML對象序列化及反序列化
下面給出的是對象的XML序列化操作:
class Person(val name:String,val age:Int){def toXML()={<person><name>{name}</name><age>{age}</age></person>} } object XMLSerialization extends App{val p=new Person("搖擺少年夢",27)println(p.toXML()) }反序列化操作:
class Person(val name:String,val age:Int){//序列化操作def toXML()={<person><name>{name}</name><age>{age}</age></person>}//反序列化操作def fromXML(xml:scala.xml.Elem):Person={new Person((xml \ "name").text,(xml \ "age").text.toInt)}override def toString()="name="+name+", age="+age } object XMLSerialization extends App{val p=new Person("搖擺少年夢",27)val xmlPerson=p.toXML()val p2=p.fromXML(xmlPerson)println(p2) }4. XML文件讀取與保存
前一小節,我們的序列化與反序列化操作都在內存中進行的,在通常的情況下都是將序列化后的XML保存在文件當中,在反序列化時再從文件中讀取,實現方式如下:
class Person(val name:String,val age:Int){def toXML()={<person><name>{name}</name><age>{age}</age></person>}def fromXML(xml:scala.xml.Elem):Person={new Person((xml \ "name").text,(xml \ "age").text.toInt)}override def toString()="name="+name+", age="+age } object XMLSerialization extends App{val p=new Person("搖擺少年夢",27)val xmlPerson=p.toXML()//保存到XML文件當中scala.xml.XML.save("person.xml", xmlPerson, "UTF-8", true, null)//從文件中加載XML文件val loadPerson=scala.xml.XML.loadFile("person.xml")val p2=p.fromXML(loadPerson)println(p2) }下面給出的是save方法的標簽
/** Saves a node to a file with given filename using given encoding* optionally with xmldecl and doctype declaration.** @param filename the filename* @param node the xml node we want to write* @param enc encoding to use* @param xmlDecl if true, write xml declaration* @param doctype if not null, write doctype declaration*/final def save(filename: String,node: Node,enc: String = encoding,xmlDecl: Boolean = false,doctype: dtd.DocType = null): Unit =5. XML模式匹配
Scala操縱XML另外一個非常強大的地方在于,它能夠用于模式匹配,從而非常靈活、方便地對XML進行處理:
import scala.xml._object PatternMatchingXML extends App{def xmlMatching(node:Node)={node match {//XML模式匹配語法,利用{}進行匹配case <persons>{sub_element}</persons>=> println(sub_element)//其它未匹配的情況case _ => println("no matching")}}//下面這條語句的執行結果:<person><name>搖擺少年夢</name></person>xmlMatching(<persons><person><name>搖擺少年夢</name></person></persons>)//下面這條語句的執行結果://no matchingxmlMatching(<persons><person><name>搖擺少年夢</name></person><person><name>搖擺少年夢</name></person></persons>) }從上述代碼可以看到,<persons>{sub_element}</persons> 只能匹配標簽<persons></persons> 中只存在單個子元素的情況,如果具有多個子元素,即子元素構成NodeSeq,則不能匹配,需要進行進一步處理,代碼如下:
object PatternMatchingXML extends App{def xmlMatching(node:Node)={node match {//_*的方式表示可以匹配多個子元素的情況,如果匹配//則將匹配的內容賦值給sub_element case <persons>{sub_element @ _*}</persons>=> println(sub_element)case _ => println("no matching")}}//下面這條語句返回的是:ArrayBuffer(<person><name>搖擺少年夢</name></person>)//數組中的每個元素都是Node類型xmlMatching(<persons><person><name>搖擺少年夢</name></person></persons>)//下面這條語句返回的是:ArrayBuffer(<person><name>搖擺少年夢</name></person>, <person><name>搖擺少年夢</name></person>)//數組中的每個元素都是Node類型xmlMatching(<persons><person><name>搖擺少年夢</name></person><person><name>搖擺少年夢</name></person></persons>) }因為返回的是ArrayBuffer,可以通過for循環遍歷對XML子元素中的內容進行提取,如:
def xmlMatching2(node:Node)={node match {case <persons>{sub_element @ _*}</persons>=> for(elm <- sub_element) println("getting "+(elm \ "name").text)case _ => println("no matching")}}//返回結果getting 搖擺少年夢xmlMatching2(<persons><person><name>搖擺少年夢</name></person></persons>)//返回結果://getting 搖擺少年夢//getting 搖擺少年夢xmlMatching2(<persons><person><name>搖擺少年夢</name></person><person><name>搖擺少年夢</name></person></persons>)總結
以上是生活随笔為你收集整理的Scala入门到精通——第二十七节 Scala操纵XML的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 人工神经网络之激活函数 -softmax
- 下一篇: Scala入门到精通——第二十八节 Sc