@amoszhou
2014-06-10T17:30:12.000000Z
字数 3162
阅读 5177
scala
在处理xml之前,首先确保我们在项目中引入了scala-xml.jar这个包。如果没有引入这个包,那么下面的那些API都无法调用。
1.1 只加载非注释结点信息
import scala.xml.XML
val root = XML.loadFile("D:/config.xml")
println(root)
最后可以通过打印结果看到结果,发现里面所有<!-- -->
注释都变成了空行。
1.2 原样加载
import scala.xml.parsing.ConstructingParser
val parser = ConstructingParser.fromFile((new File("D:/config.xml")),preserveWS = true)
val doc = parser.document()
val root2 = doc.docElem
println(root2)
val xmlContent = <config>
<!-- driver config-->
<tessafe>
<x86>
<loader gray="100" name="tessafe.sys"/>
<!-- module description-->
<module>
<m one="1" gray="100" name="proxy.mod" id="101"/>
<m one="1" gray="100" name="tessafe.mod" id="102"/>
</module>
</x86>
<x64>
<loader gray="100" name="tessafe64.sys"/>
<!-- module description-->
<module>
<m one="1" gray="100" name="proxy64.mod" id="101"/>
<m one="1" gray="100" name="tessafe64.mod" id="102"/>
</module>
</x64>
</tessafe>
<!-- other config-->
</config>
XML.save("D:/config_bak.xml",xmlContent,enc = "UTF-8",xmlDecl = true)
有2个地方要说一下的:
args1--要保存的目标文件
,args2--xml内容
。这2个是必须的参数,后续还有3个可选参数。args3--字符编码(默认是"ISO-8859-1")
,args4-是否生成xml头部申明
,即:<?xml version="1.0" encoding="utf-8" ?>
这一串。args5--即DTD文件头
Node类是所有xml节点类型的祖先,它有2个最重要的后代类(可能不是直接子类)Text和Elem。
Elem
描述的是XML元素,比如val elem = <a href="www.google.com.hk">Google</a>
一个Elem节点有5个元素:
关于scala中,xml处理API的类的层次,可以参照官方文档。
前面我们看到xml怎么写入文件,但是绝大多数情况,XML的内容是需要我们通过程序处理(比如计算,数据库读取)来构建的。那我们怎么来构建XML列?scala提供了一个工具类NodeBuffer.它是ArrayBuffer[Node]的子类
val items = new NodeBuffer
items += <li>Foo</li>
items += <li>Bar</li>
val nodes: NodeSeq = items.
事实上,上面的这种情况也比较理想,如此简单的构建XML的情况也是很少碰到的,多半要与程序打交道,那么又到了体现scala设计优势的时候了,我们来看看scala如何。
举个例子,比如我们现在有个List,存放了一些网址,我要动态生成一个HTML里面的<li>
标签,那么代码就可以如下:
val items = List("www.baidu.com","www.google.com.hk")
val xml = <ul>{for(item <- items) yield
<li>{item}</li>
}</ul>
println(xml)
也就是说我们可以在XML中,通过{}来内嵌scala代码。这是不是又是一个非常优雅的设计?在Java中,我们得死命的去拼字符串,一不小心还得拼错。
那么,又引发了一个问题,如果我的XML节点的value就是有{}这种内容,怎么办?比如<digit>字然数是:{0,1,2,3,4,5...,9}</digti>
。你永远不会是第一个发现问题的人,scala的设计者们早就考虑到这个问题了,解决办法就是再包一层{}。比如上面的部分应该是这样:<digit>字然数是:{{0,1,2,3,4,5...,9}}</digti>
这样最终就能提到你想得到的结果了。
另外有2个要注意的地方就是用{}进行内嵌的时候,千万不要在加上“”,否则当做字符串进行原样输出了。其次就是在为XML节点设置属性时,如果{}中表达式的值为null或者None时,该属性将不会被设置。这个考虑也是做的非常人性化的,省去了很多判断。
在scala中,XML节点和节点序列是不可变的,所以如果我们想编辑一个节点,只能创建一个拷贝,然后做修改。
前面,我们已经讲过Elem的5个元素(组成部分)了,如果我们不指定任何参数,就是直接原样拷贝了。我们可以将我们的修改过程,和拷贝一起完成。
例如:
1.将<ul>
修改为<ol>
val list = <ul><li>Fred</li><li>Wilma</li></ul>
val list2 = list.copy(label = "ol")
这里要注意的,2个<li>
标签是共享的,因为节点序列不可变嘛,所以也没事。
2.修改属性,用 %
操作符
val image = <img src="demo.jpg" alt="dddd"></img>
//第一个参数是命名空间,第二个是属性名,第三个是值,最后一个是额外添加的元素列表。
val image2 = image % Attribute(null,"alt","a demo image",scala.xml.Null)
println(image2)
这里要物别注意一下,最后一个参数,如果没有要增加的属性时,给值要给scala.xml.Null
,而不是普通的null
.一开始,在这是里坑了好久。
3.增加属性
val image = <img src="demo.jpg" ></img>
//第一个参数是命名空间,第二个是属性名,第三个是值,最后一个是额外添加的元素列表。
val image2 = image % Attribute(null,"alt","a demo image",scala.xml.Null)
val image3 = image % Attribute(null,"alt","a demo image",Attribute(null,"src","1001.jpg",scala.xml.Null))
println(image2)
println(image3)
这里我们注意一下,image2增加了一个alt属性,而image3则增加了一个alt属性,并且修改了src属性的值。
也就是说,当我们用 % Attribute()的时候,如果属性已经存在就修改,如果不存在就新增。