zoukankan      html  css  js  c++  java
  • Scala入门到精通——第二十七节 Scala操纵XML

    本节主要内容

    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=30
     val xml1= if(age<29) <age> {age} </age> else NodeSeq.Empty
     //<age> 28 </age
     println(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>
      //摇摆少年梦27
      println(x.text)  
    }

    这样的提取方式将XML中全部的文本内容提取出来并拼接在一起,在实际中我们可能须要精确提取,比方我仅仅想提取name元素中的内容,此时能够採用下列方式:

    val x= <person><name>摇摆少年梦</name><age>27</age></person>
    //提取name子结点,类型XPATH訪问方式
    //<name>摇摆少年梦</name>
      println(x  "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>
      //返回空NodeSeq
      println(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 matching
      xmlMatching(<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>)

    加入公众微信号。能够了解很多其他最新Spark、Scala相关技术资讯
    这里写图片描写叙述

  • 相关阅读:
    Python笔记 #17# Pandas: Merge
    MVC相关资料收集
    Python笔记 #16# Pandas: Operations
    Least slack time scheduling
    Python笔记 #15# Pandas: Missing Data
    Python笔记 #14# Pandas: Selection
    C++中const引用的是对象的时候只能调用该对象的f()const方法
    模板与泛型编程
    c++中的单例模式
    C/C++异常处理机制
  • 原文地址:https://www.cnblogs.com/zhchoutai/p/7289437.html
Copyright © 2011-2022 走看看