[关闭]
@amoszhou 2014-06-10T17:30:12.000000Z 字数 3162 阅读 5177

XML处理

scala


在处理xml之前,首先确保我们在项目中引入了scala-xml.jar这个包。如果没有引入这个包,那么下面的那些API都无法调用。

1.读取XML

1.1 只加载非注释结点信息

  1. import scala.xml.XML
  2. val root = XML.loadFile("D:/config.xml")
  3. println(root)

最后可以通过打印结果看到结果,发现里面所有<!-- -->注释都变成了空行。

1.2 原样加载

  1. import scala.xml.parsing.ConstructingParser
  2. val parser = ConstructingParser.fromFile((new File("D:/config.xml")),preserveWS = true)
  3. val doc = parser.document()
  4. val root2 = doc.docElem
  5. println(root2)

2.将XML写入文件

  1. val xmlContent = <config>
  2. <!-- driver config-->
  3. <tessafe>
  4. <x86>
  5. <loader gray="100" name="tessafe.sys"/>
  6. <!-- module description-->
  7. <module>
  8. <m one="1" gray="100" name="proxy.mod" id="101"/>
  9. <m one="1" gray="100" name="tessafe.mod" id="102"/>
  10. </module>
  11. </x86>
  12. <x64>
  13. <loader gray="100" name="tessafe64.sys"/>
  14. <!-- module description-->
  15. <module>
  16. <m one="1" gray="100" name="proxy64.mod" id="101"/>
  17. <m one="1" gray="100" name="tessafe64.mod" id="102"/>
  18. </module>
  19. </x64>
  20. </tessafe>
  21. <!-- other config-->
  22. </config>
  23. XML.save("D:/config_bak.xml",xmlContent,enc = "UTF-8",xmlDecl = true)

有2个地方要说一下的:

3.处理XML

3.1 scala中XML相关的概念

Node类是所有xml节点类型的祖先,它有2个最重要的后代类(可能不是直接子类)Text和Elem。
Elem描述的是XML元素,比如val elem = <a href="www.google.com.hk">Google</a>
一个Elem节点有5个元素:

关于scala中,xml处理API的类的层次,可以参照官方文档。

3.2 在程序中构建XML

前面我们看到xml怎么写入文件,但是绝大多数情况,XML的内容是需要我们通过程序处理(比如计算,数据库读取)来构建的。那我们怎么来构建XML列?scala提供了一个工具类NodeBuffer.它是ArrayBuffer[Node]的子类

  1. val items = new NodeBuffer
  2. items += <li>Foo</li>
  3. items += <li>Bar</li>
  4. val nodes: NodeSeq = items.

事实上,上面的这种情况也比较理想,如此简单的构建XML的情况也是很少碰到的,多半要与程序打交道,那么又到了体现scala设计优势的时候了,我们来看看scala如何。
举个例子,比如我们现在有个List,存放了一些网址,我要动态生成一个HTML里面的<li>标签,那么代码就可以如下:

  1. val items = List("www.baidu.com","www.google.com.hk")
  2. val xml = <ul>{for(item <- items) yield
  3. <li>{item}</li>
  4. }</ul>
  5. 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时,该属性将不会被设置。这个考虑也是做的非常人性化的,省去了很多判断。

3.3 修改XML元素和属性

在scala中,XML节点和节点序列是不可变的,所以如果我们想编辑一个节点,只能创建一个拷贝,然后做修改。
前面,我们已经讲过Elem的5个元素(组成部分)了,如果我们不指定任何参数,就是直接原样拷贝了。我们可以将我们的修改过程,和拷贝一起完成。
例如:

1.将<ul>修改为<ol>

  1. val list = <ul><li>Fred</li><li>Wilma</li></ul>
  2. val list2 = list.copy(label = "ol")

这里要注意的,2个<li>标签是共享的,因为节点序列不可变嘛,所以也没事。
2.修改属性,用 % 操作符

  1. val image = <img src="demo.jpg" alt="dddd"></img>
  2. //第一个参数是命名空间,第二个是属性名,第三个是值,最后一个是额外添加的元素列表。
  3. val image2 = image % Attribute(null,"alt","a demo image",scala.xml.Null)
  4. println(image2)

这里要物别注意一下,最后一个参数,如果没有要增加的属性时,给值要给scala.xml.Null,而不是普通的null.一开始,在这是里坑了好久。
3.增加属性

  1. val image = <img src="demo.jpg" ></img>
  2. //第一个参数是命名空间,第二个是属性名,第三个是值,最后一个是额外添加的元素列表。
  3. val image2 = image % Attribute(null,"alt","a demo image",scala.xml.Null)
  4. val image3 = image % Attribute(null,"alt","a demo image",Attribute(null,"src","1001.jpg",scala.xml.Null))
  5. println(image2)
  6. println(image3)

这里我们注意一下,image2增加了一个alt属性,而image3则增加了一个alt属性,并且修改了src属性的值。

也就是说,当我们用 % Attribute()的时候,如果属性已经存在就修改,如果不存在就新增。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注