Chapter 28 《Working with XML》

XML簡介

    1. XML是半結(jié)構(gòu)化的數(shù)據(jù)形式,在序列化程序數(shù)據(jù)用以在網(wǎng)絡(luò)中進(jìn)行傳輸?shù)倪^程中非常有用。不是直接將程序中的結(jié)構(gòu)化數(shù)據(jù)變?yōu)槎M(jìn)制數(shù)據(jù),而是在結(jié)構(gòu)化數(shù)據(jù)和半結(jié)構(gòu)化數(shù)據(jù)的XML形式之間進(jìn)行轉(zhuǎn)化。然后使用預(yù)先定義的庫在半結(jié)構(gòu)化數(shù)據(jù)和二進(jìn)制數(shù)據(jù)之間進(jìn)行轉(zhuǎn)換。
    1. XML中的標(biāo)簽是嵌套的,是棧的形式。
    1. Scala中可以直接以字面量的形式寫XML文件。
    1. Scala中關(guān)于XML的主要類有Elem,Node:所有XML節(jié)點(diǎn)類的抽象父類;Text:僅僅含有文字的節(jié)點(diǎn);NodeSeq:處理節(jié)點(diǎn)的序列,在某些地方可能需要使用處理節(jié)點(diǎn)序列的方法來處理單個節(jié)點(diǎn),這是可以的,Node繼承自NodeSeq
    1. XML字面量中,可以使用{}進(jìn)行轉(zhuǎn)義來求解Scala代碼的值。在{}不僅可以使用Scala code,也可以使用XML字面量來完成Node的嵌套。 xml.NodeSeq.Empty表示為空,nothing,什么都沒有的XML節(jié)點(diǎn)。在{}<>以及&字符都會被轉(zhuǎn)義。
scala>  <a> {"</a>potential security hole<a>"} </a>
res5: scala.xml.Elem = <a> &lt;/a&gt;potential security hole&lt;a&gt; </a>
    1. 不要使用String append的方式來構(gòu)建XML,例如
scala> "<a>" + "</a>potential security hole<a>" + "</a>"
res5: String = <a></a>potential security hole<a></a>
    1. 程序員允許了用戶在String中引入</a><a>來改變XML的結(jié)構(gòu),因此是不推薦使用添加字符串的形式來進(jìn)行XML的擴(kuò)建。

序列化

  • 從程序中的結(jié)構(gòu)化數(shù)據(jù)到XML的序列化,只需要使用XML字面量和{}進(jìn)行轉(zhuǎn)義計算表達(dá)式的值。如果需要在{}中包含{},則輸入兩個{}即可。
def toXML =
<cctherm>
<description>{description}</description>
<yearMade>{yearMade}</yearMade>
<dateObtained>{dateObtained}</dateObtained>
<bookPrice>{bookPrice}</bookPrice>
<purchasePrice>{purchasePrice}</purchasePrice>
<condition>{condition}</condition>
</cctherm>
scala> <a> {{{{brace yourself!}}}} </a>
res7: scala.xml.Elem = <a> {{brace yourself!}} </a>

反序列化

  • Scala中使用 XPath類似的語法來提取XML中的各個部分。
提取tag之間的文字

elem.text

scala> <a> input ---&gt; output </a>.text
res9: String = " input ---> output "
提取子元素

使用\方法,使用\\方法可以進(jìn)行遞歸的子元素搜索。

scala> <a><b><c>hello</c></b></a> \"a"
res13: scala.xml.NodeSeq = NodeSeq()
scala> <a><b><c>hello</c></b></a> \\"a"
res14: scala.xml.NodeSeq =
NodeSeq(<a><b><c>hello</c></b></a>)  //是可以包含自身
提取屬性

使用\方法和\\方法,加入@符號

scala> val joe = <employee name="Joe" rank="code monkey" serial="123"/>
scala> joe \"@name"
res17:  scala.xml.NodeSeq = Joe
反序列化

從上面的提取每個部分元素的方法對XML進(jìn)行反序列化生成結(jié)構(gòu)化的數(shù)據(jù)。


XML和字節(jié)流之間的轉(zhuǎn)換

    1. 最后一個轉(zhuǎn)換:XML數(shù)據(jù)和字節(jié)流之間的轉(zhuǎn)換。
    1. 最好使用庫來進(jìn)行XML的轉(zhuǎn)換,可以確定字符編碼,否則需要自己追蹤字符的編碼。
將XML轉(zhuǎn)換為字節(jié)數(shù)據(jù):
scala.xml.XML.save("therm1.xml", node)
從字節(jié)數(shù)據(jù)中獲取數(shù)據(jù)生成XML
val loadnode = xml.XML.loadFile("therm1.xml") loadnode: scala.xml.Elem = ……
  • 這些都是基礎(chǔ)的方法,還有許多針對不同讀寫流和輸入輸出流來序列化和反序列化XML的方法。

模式匹配

  • XML使用模式匹配:模式看起來就像是XML字面量。最主要的區(qū)別是在{}中插入的代碼不是一個表達(dá)式而是一個模式。
匹配單個節(jié)點(diǎn)
def proc(node: scala.xml.Node): String = node match {
case <a>{contents}</a> => "It's an a: " + contents //這里的<a>與content之間的空格或者換行在node中有需要有強(qiáng)制性的匹配
case <b>{contents}</b> => "It's a b: " + contents
case _ => "It's something else."
}
可以匹配的XML為<a>It's a comment</a>,不能匹配的為<a><em>It's a comment</em></a>
匹配一個節(jié)點(diǎn)序列,而不是單個節(jié)點(diǎn)
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."
}
多次使用模式匹配,跳過空白字符
  • 使用變量綁定,將_*中的內(nèi)容綁定到contents上。模式匹配可以用來跳過XML中的空白字符。
val catalog =
  <catalog> //空白字符
    </cctherm>
       ……
    </cctherm>
    <cctherm>
        ……
   </cctherm>
 </catalog> // catalog中共有5個子節(jié)點(diǎn),有3個空白字符節(jié)點(diǎn),兩個cctherm節(jié)點(diǎn)
// 沒有處理<catalog></catalog>前后的空白字符
catalog match {
    case <catalog>{therms @ _*}</catalog> =>
        for (therm <- therms)
            println("processing: " +
                    (therm \"description").text)
}
//進(jìn)一步使用模式匹配<cctherm>{_*}</cctherm生成for循環(huán)的迭代器。處理了空白字符
catalog match {
    case <catalog>{therms @ _*}</catalog> =>
        for (therm @ <cctherm>{_*}</cctherm> <-
                     therms)
            println("processing: " +
                    (therm \"description").text)
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容