快学Scala习题解答—第十六章 XML处理

16.XML处理

16.1<fred/>(0) 得到什么?<fred/>(0)(0)呢?为什么?

回答:<fred/>(0) 得到一个scala.xml.Node,<fred/>(0)(0)也是得到scala.xml.Node

因为scala.xml.Node 实现了方法 def apply(i: Int): Node,所以支持串接调用。

注意:scala-xml-x.x.x.jar 需要另外导入。

scala> val a = <fred/>
a: scala.xml.Elem = <fred/>
scala> a(0)
res2: scala.xml.Node = <fred/>
scala> a(0)(0)
res3: scala.xml.Node = <fred/>
scala> a(0)(0)(0)
res4: scala.xml.Node = <fred/>
scala> a(0)(0)(0)(0)
res5: scala.xml.Node = <fred/>
? 

16.2如下代码的值是什么?

<ul>

    <li>Opening bracket: [</li>

    <li>Closing bracket: ]</li>   

    <li>Opening brace: {</li>   

  <li>Closing brace: }</li>   

</ul>  

你如何修复它?

回答:会有编译错误。要在XML字面量中包含左花括号和右花括号,连续写两个即可。

package ex16_02
import scala.xml._
object Main extends App{
/*
Multiple markers at this line:
in XML literal: in XML content, please use '}}' to express '}'
I encountered a '}' where I didn't expect one, maybe this tag isn't closed <li>
I encountered a '}' where I didn't expect one, maybe this tag isn't closed <li>
 */
  val a =
<ul>
    <li>Opening bracket: [</li>
    <li>Closing bracket: ]</li>   
    <li>Opening brace: {{</li>   
  <li>Closing brace: }}</li>   
</ul>
     
  println(a)
}
/*output:
<ul>
  <li>Opening bracket: [</li>
  <li>Closing bracket: ]</li>   
  <li>Opening brace: {</li>   
  <li>Closing brace: }</li>   
</ul>
*/

?

16.3 比对 <li>Fred</li> match { case <li>{Text(t)}</li> => t } 和

<li>{"Fred"}</li> match { case <li>{Text(t)}</li> => t }

为什么它们的行为不同?

回答:内嵌表达式中的字符串并不会被转成Text节点而是Atom[String]节点。这和普通的Text节点还是有区别的——Text是Atom[String]的子类。

这对于保存文档没有问题。但如果你事后打算以Text节点的模式对它做匹配时,匹配会失败。像这种情况你应该插入Text节点而不是字符串。

import scala.xml._
object Main extends App {
  val a = <li>Fred</li> match { case <li>{ Text(t) }</li> => t }
  //val b = <li>{ "Fred" }</li> match { case <li>{ Text(t) }</li> => t }
  val c = <li>{ Text("Fred") }</li> match { case <li>{ Text(t) }</li> => t }
  //println("a=" + a)
  println("c=" + c)
}
/*output:
a=Fred
b: Exception in thread "main" scala.MatchError: <li>Fred</li> (of class scala.xml.Elem)
c=Fred
*/

?

16.4读取一个XHTML文件并打印所有不带alt属性的img元素。

import scala.xml._
object Main extends App {
  val root = XML.loadFile("./src/test.xhtml")
  val imgs: NodeSeq = root \\ "img"
  // img \ "@alt " 's type is scala.xml.NodeSeq
  for (img <- imgs if (img \ "@alt").text == "") println(img)
}
/*output:
<img src="hamster.jpg"/>
<img src="frog.jpg"/>
*/
test.xhtml

<html>
<head>
<title>My Scala</title>
</head>
<body>
<p>Hello Scala</p>
<p><img src="hamster.jpg"/></p>
<p><img src="frog.jpg"/></p>
<p><img src="dog.jpg" alt="inu"/></p>
</body>
</html>

? 

16.5打印XHTML文件中所有图像的名称。即,打印所有位�%@A�img元素内的src属性值。

import scala.xml._
object Main extends App {
  val root = XML.loadFile("./src/test.xhtml")
  val imgs: NodeSeq = root \\ "img"
  // img \ "@alt " 's type is scala.xml.NodeSeq
  imgs.foreach { x => println(x \ "@src" text) }
}
/*output:
hamster.jpg
frog.jpg
dog.jpg
*/

?

16.6读取XHTML文件并打印一个包含了文件中给出的所有超链接及其URL的表格。

即,打印所有a元素的child文本和href属性。

import scala.xml._
object Main extends App {
  val root = XML.loadFile("./src/oschina.xhtml")
  val imgs: NodeSeq = root \\ "a"
  imgs.foreach { x => 
    val child = x.child
    println("%s: %s".format(child(0).text, x.attribute("href").getOrElse("")))
    }
}
/*output:
Android: http://www.oschina.net/app
iPhone: http://www.oschina.net/app
WP7: http://www.oschina.net/app
*/

?

oschina.xml:

<html>
<head>
<title>My Scala</title>
</head>
<body>
<p>Hello Scala</p>
<p><img src="hamster.jpg"/></p>
<p><img src="frog.jpg"/></p>
<p><img src="dog.jpg" alt="inu"/></p>
<ul>
<li><a href="http://www.oschina.net/app" class='android' title='Android客户端'>Android</a></li>
<li><a href="http://www.oschina.net/app" class='iphone' title='iPhone 客户端'>iPhone</a></li>
<li><a href="http://www.oschina.net/app" class='wp7' title='Windows Phone 客户端'>WP7</a></li>
</ul>
</body>
</html>

? 

16.7编写一个函数,带一个类型为Map[String, String]的参数,返回一个dl元素,其中针对映射中每个键对应有一个dt,每个值对应有一个dd。例如:

Map("A" -> "1", "B" -> "2")

应产出 <dl><dt>A</dt><dd>1</dd><dt>B</dt><dd>2</dd></dl>

import scala.xml._
object Main extends App {
 def genDl(input: Map[String,String])={
   <dl>{for((k,v) <- input) yield <dt>{k}</dt><dd>{v}</dd>}</dl>
 }
  
 val input = Map("A" -> "1", "B" -> "2")
 println(genDl(input))
}
/*output:
<dl><dt>A</dt><dd>1</dd><dt>B</dt><dd>2</dd></dl>
*/

?

16.8编写一个函数,接受dl元素,将它转成Map[String,String]。该函数应该是前一个练习中的反向处理,前提是所有dt后代都是唯一(各不相同)的。

import scala.xml._
import scala.collection.mutable.Map
object Main extends App {
  def dl2map(input: scala.xml.Elem): Map[String, String] = {
    val map = Map[String, String]()
    val keys = input \ "dt"
    val values = input \ "dd"
    for (i <- 0 until keys.size) map += keys(i).text -> values(i).text
    map
  }
  val input = <dl><dt>A</dt><dd>1</dd><dt>B</dt><dd>2</dd></dl>
  val obj = dl2map(input)
  println(obj)
}
/*output:
Map(A -> 1, B -> 2)
*/

?

16.9对一个XHTML文档进行变换,对所有不带alt属性的img元素添加一个alt="TODO"属性,其余内容完全不变。

import scala.xml._
import scala.xml.transform._
object Main extends App {
  def transform(filename: String) {
    val root = XML.loadFile(filename)
    val rule1 = new RewriteRule {
      override def transform(n: Node) = n match {
        case x @ <img/> => if (x.attributes("alt") == null) x.asInstanceOf[Elem] % Attribute(null, "alt", "TODO", scala.xml.Null) else x
        case _ => n
      }
    }
    val transformed = new RuleTransformer(rule1).transform(root)
    //println(transformed)
    scala.xml.XML.save("./src/test_new.xhtml", transformed(0))
  }
  transform("./src/test.xhtml")
}
/*output:
<html>
<head>
<title>My Scala</title>
</head>
<body>
<p>Hello Scala</p>
<p><img alt="TODO" src="hamster.jpg"/></p>
<p><img alt="TODO" src="frog.jpg"/></p>
<p><img alt="inu" src="dog.jpg"/></p>
</body>
</html>
*/


16.10编写一个函数,读取XHTML文档,执行前一个练习中的变换,并保存结果。确保保存了DTD及所有CDATA内容。

import scala.xml._
import scala.xml.transform._
import scala.xml.parsing.ConstructingParser
import scala.xml.dtd._
object Main extends App {
  def transform(filename: String) {
    val parser = ConstructingParser.fromFile(new java.io.File(filename), preserveWS = true)
    val doc = parser.document
    val root = doc.docElem
    val rule1 = new RewriteRule {
      override def transform(n: Node) = n match {
        case x @ <img/> => if (x.attributes("alt") == null) x.asInstanceOf[Elem] % Attribute(null, "alt", "TODO", scala.xml.Null) else x
        case _          => n
      }
    }
    val transformed = new RuleTransformer(rule1).transform(root)
    //println(transformed)
    scala.xml.XML.save("./src/cdata_new.xhtml", transformed(0),
      enc = "UTF-8",
      xmlDecl = true,
      doctype = DocType("html",
        PublicID("-//W3C//DTD XHTML 1.0 Strict//EN",
          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"),
        Nil))
  }
  transform("./src/cdata.xhtml")
}
/*output:
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<title>My Scala</title>
<script>
<![CDATA[
function matchwo(a,b)
{
if (a < b && a < 0) then
  {
  return 1;
  }
else
  {
  return 0;
  }
}
]]>
</script>
</head>
<body>
<!-- This is a comment -->
<p>Hello Scala</p>
<p><img alt="TODO" src="hamster.jpg"/></p>
<p><img alt="TODO" src="frog.jpg"/></p>
<p><img alt="inu" src="dog.jpg"/></p>
</body>
</html>
*/
原文博客地址:http://blog.csdn.net/u011225629/article/details/47618015

?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值