博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Scala入门到精通——第二十七节 Scala操纵XML
阅读量:5878 次
发布时间:2019-06-19

本文共 6503 字,大约阅读时间需要 21 分钟。

本节主要内容

  1. XML 字面量
  2. XML内容提取
  3. XML对象序列化及反序列化
  4. XML文件读取与保存
  5. XML模式匹配

1. XML 字面量

XML是一种非常重要的半结构化数据表示方式,目前大量的应用依赖于XML,这些应用或利用XML作为数据交换格式,或利用XML进行文件配置等。像JAVA、C++及其它流行的程序开发语言都是依赖于第三方库来实现XML的操作,例如JAVA经常通过JDOM,DOM4J等XML处理工具进行XML的操纵,但Scala提供了对XML的原生支持,通过scala.xml._包下的类或对象可以进行任何的XML操作。下面的代码演示了Scala中如何定义XML字面量。

scala> var x: scala.xml.Elem = 
xuetuwuyou
http://www.xuetuwuyou.com/
x: scala.xml.Elem =
xuetuwuyou
http://www.xuetuwuyou.com/
scala>
xuetuwuyou
http://www.xuetuwuyou.com/
res8: scala.xml.Elem =
xuetuwuyou
http://www.xuetuwuyou.com/

通过上面的代码不能发现,scala会自动地对XML进行解析,并识别为scala.xml.Elem类型。scala中与XML相关的包和类很多,具体如下图所示:

这里写图片描述

在深入讲解Scala操纵XML之前,先对几个主要的术语进行介绍:

这里写图片描述
图中描述了属性、根元素、子元素、元素及文本的概念及它们之间的关联关系,所以的文本、元素被统称为节点(Node)。下面给出的scala XML中的几个重要的类:

  • Node类。它的一个抽象类,用于对象XML中的所有节点进行抽象:
    这里写图片描述
  • Text类,仅包含文本的节点,例如<url>http://www.xuetuwuyou.com/</url> 中的就是一种Text对象
  • NodeSeq类,它同样是一个抽象类,指的是节点的序列,Node继承自NodeSeq,可以看Node可作是NodeSeq只有一个元素的情况。

scala中的XML中可以执行scala表达式,例如

val s="http://www.xuetuwuyou.com/" val xmlUrl= {
" "+s+" "}
// http://www.xuetuwuyou.com/ println(xmlUrl) val age=30 val xml1= if(age<29)
{age}
else NodeSeq.Empty //
28
79
val xml2=
{
29+50}
println(xml2)

2. XML内容提取

提取XML中的文本:

object ExtractXMLText extends App{
val x=
摇摆少年梦
27
//摇摆少年梦27 println(x.text) }

这种提取方式将XML中所有的文本内容提取出来并拼接在一起,在实际中我们可能需要精确提取,比如我只想提取name元素中的内容,此时可以采用下列方式:

val x= 
摇摆少年梦
27
//提取name子结点,类型XPATH访问方式//
摇摆少年梦
println(x \ "name")//提取name中的文本 println((x \ "name").text)scala> x \ "age"res2: scala.xml.NodeSeq = NodeSeq(
27
)

x \ “age” 这种子元素的提取方式,返回的类型是scala.xml.NodeSeq

\的方式只能提取子元素,不能提取子元素的子元素,例如:

val x= 
摇摆少年梦
27
张三
29
李四
30
//返回空NodeSeq println(x \ "name") // \\提取二级子元素 //
摇摆少年梦
张三
李四
println(x \\ "name")

通过\和\可以提取任何XML的子元素及其文本内容,但如果XML元素带有属性,那又如何提取呢?

val x= 
张三
29
李四
30
//用@方式提取name属性 //摇摆少年梦 println(x \\ "@name")

3. XML对象序列化及反序列化

下面给出的是对象的XML序列化操作:

class Person(val name:String,val age:Int){
def toXML()={
{name}
{age}
}}object XMLSerialization extends App{
val p=new Person("摇摆少年梦",27) println(p.toXML())}

反序列化操作:

class Person(val name:String,val age:Int){
//序列化操作 def toXML()={
{name}
{age}
} //反序列化操作 def fromXML(xml:scala.xml.Elem):Person={ new Person((xml \ "name").text,(xml \ "age").text.toInt) } override def toString()="name="+name+", age="+age}object XMLSerialization extends App{
val p=new Person("摇摆少年梦",27) val xmlPerson=p.toXML() val p2=p.fromXML(xmlPerson) println(p2)}

4. XML文件读取与保存

前一小节,我们的序列化与反序列化操作都在内存中进行的,在通常的情况下都是将序列化后的XML保存在文件当中,在反序列化时再从文件中读取,实现方式如下:

class Person(val name:String,val age:Int){
def toXML()={
{name}
{age}
} def fromXML(xml:scala.xml.Elem):Person={ new Person((xml \ "name").text,(xml \ "age").text.toInt) } override def toString()="name="+name+", age="+age}object XMLSerialization extends App{
val p=new Person("摇摆少年梦",27) val xmlPerson=p.toXML() //保存到XML文件当中 scala.xml.XML.save("person.xml", xmlPerson, "UTF-8", true, null) //从文件中加载XML文件 val loadPerson=scala.xml.XML.loadFile("person.xml") val p2=p.fromXML(loadPerson) println(p2)}

下面给出的是save方法的标签

/** Saves a node to a file with given filename using given encoding   *  optionally with xmldecl and doctype declaration.   *   *  @param filename the filename   *  @param node     the xml node we want to write   *  @param enc      encoding to use   *  @param xmlDecl  if true, write xml declaration   *  @param doctype  if not null, write doctype declaration   */  final def save(    filename: String,    node: Node,    enc: String = encoding,    xmlDecl: Boolean = false,    doctype: dtd.DocType = null    ): Unit =

5. XML模式匹配

Scala操纵XML另外一个非常强大的地方在于,它能够用于模式匹配,从而非常灵活、方便地对XML进行处理:

import scala.xml._object PatternMatchingXML extends App{
def xmlMatching(node:Node)={ node match { //XML模式匹配语法,利用{}进行匹配 case
{sub_element}
=> println(sub_element) //其它未匹配的情况 case _ => println("no matching") } } //下面这条语句的执行结果:
摇摆少年梦
xmlMatching(
摇摆少年梦
) //下面这条语句的执行结果: //no matching xmlMatching(
摇摆少年梦
摇摆少年梦
)}

从上述代码可以看到,<persons>{sub_element}</persons> 只能匹配标签<persons></persons> 中只存在单个子元素的情况,如果具有多个子元素,即子元素构成NodeSeq,则不能匹配,需要进行进一步处理,代码如下:

object PatternMatchingXML extends App{  def xmlMatching(node:Node)={     node match {       //_*的方式表示可以匹配多个子元素的情况,如果匹配       //则将匹配的内容赋值给sub_element        case 
{sub_element @ _*}
=> println(sub_element) case _ => println("no matching") } } //下面这条语句返回的是:ArrayBuffer(
摇摆少年梦
) //数组中的每个元素都是Node类型 xmlMatching(
摇摆少年梦
) //下面这条语句返回的是:ArrayBuffer(
摇摆少年梦
,
摇摆少年梦
) //数组中的每个元素都是Node类型 xmlMatching(
摇摆少年梦
摇摆少年梦
)}

因为返回的是ArrayBuffer,可以通过for循环遍历对XML子元素中的内容进行提取,如:

def xmlMatching2(node:Node)={     node match {       case 
{sub_element @ _*}
=> for(elm <- sub_element) println("getting "+(elm \ "name").text) case _ => println("no matching") } } //返回结果getting 摇摆少年梦 xmlMatching2(
摇摆少年梦
) //返回结果: //getting 摇摆少年梦 //getting 摇摆少年梦 xmlMatching2(
摇摆少年梦
摇摆少年梦
)

添加公众微信号,可以了解更多最新Spark、Scala相关技术资讯

这里写图片描述

你可能感兴趣的文章
为什么现在都用面向对象开发,为什么现在都用分层开发结构?
查看>>
【离散数学】 SDUT OJ 偏序关系
查看>>
写给学弟学妹的产品入门建议(持续更新)
查看>>
view视图总结
查看>>
oracle11g 数据库导出报“ EXP-00003:
查看>>
201521123009 《Java程序设计》第11周学习总结
查看>>
可解释的机器学习
查看>>
Python3之多线程学习
查看>>
MVC和MTV结构分析
查看>>
(转)微信网页扫码登录的实现
查看>>
mariadb启动报错:[ERROR] Can't start server : Bind on unix socket: Permission denied
查看>>
nginx的信号量
查看>>
云im php,网易云IM
查看>>
河南农业大学c语言平时作业答案,河南农业大学2004-2005学年第二学期《C语言程序设计》期末考试试卷(2份,有答案)...
查看>>
c语言打开alist文件,C语言 文件的打开与关闭详解及示例代码
查看>>
c语言 中的共用体和结构体如何联合定义,结构体(Struct)、联合体(Union)和位域
查看>>
iOS UITableView表视图滚动隐藏UINavigationController导航栏
查看>>
SDL如何嵌入到QT中?!
查看>>
$(document).ready()
查看>>
P1026 统计单词个数
查看>>