本节主要内容

  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 = <site><name>xuetuwuyou</name><url>http://www.xuet
uwuyou.com/</url></site>
x: scala.xml.Elem = <site><name>xuetuwuyou</name><url>http://www.xuetuwuyou.com/
</url></site>scala> <site><name>xuetuwuyou</name><url>http://www.xuetuwuyou.com/</url></site>res8: scala.xml.Elem = <site><name>xuetuwuyou</name><url>http://www.xuetuwuyou.c
om/</url></site>

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

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

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

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

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

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

2. XML内容提取

提取XML中的文本:

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

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

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

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

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

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

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

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

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

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


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

反序列化操作:

class Person(val name:String,val age:Int){//序列化操作def toXML()={<person><name>{name}</name><age>{age}</age></person>}//反序列化操作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()={<person><name>{name}</name><age>{age}</age></person>}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 <persons>{sub_element}</persons>=> println(sub_element)//其它未匹配的情况case _ => println("no matching")}}//下面这条语句的执行结果:<person><name>摇摆少年梦</name></person>xmlMatching(<persons><person><name>摇摆少年梦</name></person></persons>)//下面这条语句的执行结果://no matchingxmlMatching(<persons><person><name>摇摆少年梦</name></person><person><name>摇摆少年梦</name></person></persons>)
}

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

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

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

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

Scala入门到精通——第二十七节 Scala操纵XML相关推荐

  1. Scala入门到精通——第二十节 类型参数(二)

    本节主要内容 Ordering与Ordered特质 上下文界定(Context Bound) 多重界定 类型约束 1. Ordering与Ordered特质 在介绍上下文界定之前,我们对Scala中的 ...

  2. Scala入门到精通——第二十一节 类型参数(三)-协变与逆变

    本节主要内容 协变 逆变 类型通匹符 1. 协变 协变定义形式如:trait List[+T] {} .当类型S是类型A的子类型时,则List[S]也可以认为是List[A}的子类型,即List[S] ...

  3. Scala入门到精通——第二十八节 Scala与JAVA互操作

    本节主要内容 JAVA中调用Scala类 Scala中调用JAVA类 Scala类型参数与JAVA泛型互操作 Scala与Java间的异常处理互操作 1. JAVA中调用Scala类 Java可以直接 ...

  4. Scala入门到精通——第十七节 类型参数(一)

    本节主要内容 类型变量界定(Type Variable Bound) 视图界定(View Bound) 上界(Upper Bound)与下界(Lower Bound) 1. 类型变量界定(Type V ...

  5. Scala入门到精通——第十节 Scala类层次结构、Traits初步

    本节主要内容 Scala类层次结构总览 Scala中原生类型的实现方式解析 Nothing.Null类型解析 Traits简介 Traits几种不同使用方式 1 Scala类层次结构 Scala中的类 ...

  6. Scala入门到精通——第二十九节 Scala数据库编程

    本节主要内容 Scala Mavenproject的创建 Scala JDBC方式訪问MySQL Slick简单介绍 Slick数据库编程实战 SQL与Slick相互转换 本课程在多数内容是在官方教程 ...

  7. Scala入门到精通——第二十五节 提取器(Extractor)

    本节主要内容 apply与unapply方法 零变量或变量的模式匹配 提取器与序列模式 scala中的占位符使用总结 1. apply与unapply方法 apply方法我们已经非常熟悉了,它帮助我们 ...

  8. Scala入门到精通——第二十四节 高级类型 (三)

    本节主要内容 Type Specialization Manifest.TypeTag.ClassTag Scala类型系统总结 在Scala中,类(class)与类型(type)是两个不一样的概念. ...

  9. Scala入门到精通—— 第二节Scala基本类型及操作、程序控制结构

    本节主要内容 Scala基本类型 基本类型操作 Scala程序控制结构 Scala基本类型 Scala中的基本数据类型如下图: (来源:Programming in scala) 从上表中可以看出,S ...

最新文章

  1. 阿里巴巴为什么能抗住90秒100亿?看完这篇你就明白了!
  2. R语言基于LASSO进行特征筛选(feature selection)
  3. 火电电厂相关业务知识
  4. NYOJ 485 A*B Problem
  5. C/Cpp / 模板类中可以使用虚函数吗?模板成员函数可以是虚函数吗?
  6. 20170819 - 今日技能封装 - A
  7. Python之调用JS的方式
  8. 有关 给Layout设置监听事件后,与Layout子控件的响应关系
  9. SQL存储过程调试方法
  10. 推荐一个免费绘制软件架构图的网站
  11. jvm 的内存分配方式
  12. python运维都做些什么_python运维工程师主要干什么
  13. uniapp引入字体包——DIN
  14. 福利卡巴斯基一年免费以及一些使用软件
  15. Yigo平台环境配置——详细步骤
  16. 语音转文字软件哪个好,这三款值得收藏
  17. 初创公司,如何找到靠谱的产品经理?
  18. 阿里巴巴python招聘_作为应届生,我在阿里巴巴的成功面试经历!
  19. 计算机上根号是哪一个,电脑上怎么哪个键是数学中的开根号啊
  20. ts3.03.x cocos实现九宫格/跑马灯抽奖

热门文章

  1. 进行面向对象设计时,就一个类而言,应该仅有一个引起它变化 的原因,这属于()设计原则。【最全!最详细解析!】
  2. 在word中给公式添加序号
  3. [leetcode] 21.合并两个有序链表
  4. php做的物资管理系统,基于WEB的物资管理信息系统
  5. Android 通过字符串来获取R下面资源的ID 值 文字资源
  6. Eclipse下搭建C语言开发环境
  7. mysql不存在就批量新增_mysql批量插入,存在则修改,不存在则插入
  8. 合并远程仓库到本地_使用命令行把你新建的项目上传到GitHub仓库中
  9. 神兽来了服务器维护,20191204维护公告解读
  10. 在php中页面布局 3列左右侧固定中间自适应居中,css三列布局--两边固定中间自适应和中间固定两边自适应...