《快学Scala》(英文版:《Scala for the Impatient》),代码已传github:
https://github.com/vernonzheng/scala-for-the-Impatient
书为第一版。scala为2.11.4,jdk1.7.45,操作系统Mac OS X Yosemite 10.10.1。
第十六章 XML处理
16.1
(0)得到什么?(0)(0)呢?为什么?
1 2 3 4 5
| scala> println(<fred/>(0)) <fred/> scala> println(<fred/>(0)(0)) <fred/>
|
因为都是scala.xml.Node,是NodeSeq的子类,等同于长度为1的序列。
16.2
如下代码的值是什么?
- Opening bracket:[
- Closing bracket:]
- Opening bracket:{
- Closing bracket:}
你如何修复它?
1 2 3 4 5 6 7 8 9 10 11 12 13
| scala> <ul> | <li>Opening bracket:[</li> | <li>Closing bracket:]</li> | <li>Opening bracket:\{\{</li> | <li>Closing bracket:\}\}</li> | </ul> res9: scala.xml.Elem = <ul> <li>Opening bracket:[</li> <li>Closing bracket:]</li> <li>Opening bracket:{</li> <li>Closing bracket:}</li> </ul>
|
花括号作为字面量,需要连写两个
16.3
对比
Fred match { case
{Text(t)} => t }
和
{“Fred”} match { case
{Text(t)} => t}
为什么它们的行为不同?
scala 2.11.4查不到Text api。。略
16.4
读取一个XHTML文件并打印所有不带alt属性的img元素
1 2 3 4 5 6 7 8 9 10
| import scala.xml.XML var html = "<html><head><title>第一个网页</title></head><body><p><img alt='a'><img src='1'></img></p></body></html>" val images = (html \\ "img").filterNot(_.attributes("alt").isDefined) val images1 = html match{ case n @ <img/> if (!n.attributes("alt")) => n } println(images.mkString("\n")); println(images1.mkString("\n"));
|
16.5
打印XHTML文件中所有图像的名称,即打印所有位于img元素内的src属性值
1 2 3 4 5 6 7 8 9 10
| import scala.xml.XML var html = "<html><head><title>第一个网页</title></head><body><p><img alt='a'><img src='1'></img></p></body></html>" val images = (html \\ "img").flatMap(_.attributes("src")) val images1 = html match{ case n @ <img/> => Some(n.attributes("src")) } println(images.mkString("\n")); println(images1.mkString("\n"));
|
16.6
读取XHTML文件并打印一个包含了文件中给出的所有超链接及其url的表格。即,打印所有a元素的child文本和href属性。
1 2 3 4 5 6
| import scala.xml._ val html = "" val links = (html \\ "a") map { (x: Node) => (x.attribute("href").getOrElse("").toString, x.text) } filter {_._1.startsWith("http")} println(links.mkString("\n"));
|
16.7
编写一个函数,带一个类型为Map[String,String]的参数,返回一个dl元素,其中针对映射中每个键对应有一个dt,每个值对应有一个dd,例如:
Map(“A”->”1”,”B”->”2”)
应产出
- A
- 1
- B
- 2
1 2 3 4 5 6 7
| def mapToHTML(map: Map[String, String]) = { <dl>{for ((k,v) <- map) yield <dt>{k}</dt><dd>{v}</dd>}</dl> } val x = Map("A" -> "1", "B" -> "2") println(mapToHTML(x))
|
16.8
编写一个函数,接受dl元素,将它转成Map[String,String]。该函数应该是前一个练习中的
反向处理,前提是所有dt后代都是唯一的。
1 2 3 4 5 6 7 8
| def htmlToMap(str:String):Map[String,String] = { val dtMap = (str \\ "dt").toMap val ddMap = (str \\ "dd").toMap dtMap.zip(ddMap) } val html = <dl><dt>A</dt><dd>1</dd><dt>B</dt><dd>2</dd></dl> println(htmlToMap(html).mkString(","))
|
16.9
对一个XHTML文档进行变换,对所有不带alt属性的img元素添加一个alt=”TODO”属性,其他内容完全不变。
1 2 3 4 5 6 7
| import scala.xml._ val html = "" val replaceNoneAlt = html match{ case img @ <img/> if(_.attribute(alt)=="NONE") => img % Attribute(null,"alt","TODO",null) case _ => html } println(replaceNoneAlt)
|
16.10
编写一个函数,读取XHTML文档,执行前一个练习中的变换,并保存结果。确保保留了DTD以及所有CDATA内容。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| import xml._ import xml.transform._ import xml.parsing.ConstructingParser import xml.dtd.DocType import java.io.File val doc = ConstructingParser.fromFile(new File("./test.xml"), true).document val a = doc.docElem val imgRule = new RewriteRule { override def transform(n:Node) = n match { case i @ <img>{_*}</img> if(i.attribute("alt") == None) => i % Attribute(null, "alt", "TODO", Null) case _ => n } } val result = new RuleTransformer(imgRule).transform(a) XML.save("./test.xml", result(0), "UTF-8", false, DocType("html", doc.dtd.externalID, Nil))
|
参考:
《快学Scala》:http://book.douban.com/subject/19971952/
(转载本站文章请注明作者和出处 Vernon Zheng(郑雪峰) – vernonzheng.com ,请勿用于任何商业用途)