《快学scala》习题解答-第十六章-XML处理

《快学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 ,请勿用于任何商业用途)