这是一篇《快学scala》的读书笔记,需要具备Scala语言的基础,欢迎读者与我一起探讨,或者教我新知识呀~
16.1 XML字面量
Scala对xml有内建支持,直接用xml代码就行
import scala.xml.Elem
import scala.xml.NodeBuffer
val doc:Elem = <html><head><title>Fred's</title></head></html>
val item:NodeBuffer = <li>Fred</li><li>wilma</li>
16.2 XML节点
Node类是所有XML节点类型的祖先,两个最重要的子类是Text和Elem。
用child方法遍历父节点下面的每一个子节点
val ls:Elem = <a herf="www.baidu.com">the<em>scala</em><em>yoyo</em>language</a>
for(x <- ls.child)
println(x)
输出结果:
the
scala
yoyo
language
代码:
val ls:Elem = <a herf="www.baidu.com">the<em><li>hello</li>scala</em><em>yoyo</em>language</a>
for(x <- ls.child if !x.child.isEmpty)
println(x.child)
输出结果:
ArrayBuffer(<li>hello</li>, scala)
ArrayBuffer(yoyo)
通过变成的方式构建节点序列,可以使用NodeBuffer,是ArrayBuffer[Node]的子类,可以被隐式转换为NodeSeq,转换之后就不能再继续修改它,因为xml节点序列是不可变的
import scala.xml.{Node, NodeSeq}
val items = new NodeBuffer
items += <li>Fred</li>
items += <li>Wilma</li>
val nodes:NodeSeq = items
16.3 元素属性
要处理某个元素的属性键和值,可以使用attributes属性,返回Option类型的节点序列
val ls:Elem = <a href="www.baidu.com">the<em><li>hello</li>scala</em><em>yoyo</em>language</a>
val url: scala.Seq[Node] = ls.attributes("href")
val url1:String= ls.attributes("href").text
println(url1)
输出结果:www.baidu.com
通过调用 text方法返回String类型结果,也可以通过下面的方法避免没有这个属性返回null的结果,如果没有返回空
val url2 = ls.attributes.get("alt").getOrElse(Text(""))
println(url2)
遍历节点的所有属性:
val elem1 = <p class="nihao" type="wawa"></p>
for(attr <- elem1.attributes)
println(attr.key,attr.value.text)
val map:Map[String,String] = elem1.attributes.asAttrMap
println(map)
两种方式都可以遍历节点的所有属性,第一种方式的attr类型是MetaData,第二种方式返回的是键值对的map
16.4 内嵌表达式
可以在xml字面量中包含Scala的代码块
val items = List(2,3,5)
val elem = <ul>{for(i <- items)yield <li>{i}</li>}</ul>
println(elem)
16.5 在属性中使用表达式
可以用Scala表达式来计算属性值
val e = <a id={new Atom[Int](1)}></a>
println(e.attributes("id").text)
val description = "TOD"
val q = <img alt={if(description == "TODO") null else description}>yolo</img>
println(q.attributes.get("alt").getOrElse(Text("")))
16.8 模式匹配
可以在模式匹配表达式中使用xml字面量
var nodeLs = List(<img/>)
nodeLs = <li>yolo</li> :: nodeLs
nodeLs = <ul>lala<li>yilia</li></ul> :: nodeLs
nodeLs.foreach(_ match {
case <img/> => println("img")
case <li>{v}</li> => println(v)
case <ul>{_*}</ul> => println("lala")
case _ => println("")
})
可以用下面的方式匹配文本
<li>{Text(v)}</li> => v
<li>v</li> => v.text
XML模式不能有属性,如果要匹配属性,需要用守卫
var nodeLs = List(<img/>)
nodeLs = <li class="name">yolo</li> :: nodeLs
nodeLs = <ul>lala<li>yilia</li></ul> :: nodeLs
nodeLs.foreach(_ match {
case <img/> => println("img")
case n @ <li>{_}</li> if (n.attributes("class").text == "name")=> println(n)
case <ul>{_*}</ul> => println("lala")
case _ => println("")
})
16.9 修改元素和属性
xml节点和节点序列是不可变的,如果要编辑一个节点,需要创建一个拷贝
val list = <ul><li>Fred</li><li>Wilma</li></ul>
val list2 = list.copy(label = "ol")
println(list2)
结果输出:
- Fred
- Wilma
新旧两个列表的后代是共享的,要添加一个后代,可以像下面这样调用copy
val list = <ul><li>Fred</li><li>Wilma</li></ul>
val list2 = list.copy(label = "ol",child = list.child ++ <li>another</li>)
println(list2)
更多内容请见我的个人博客:AlisaBen