Chapter 28 《Working with XML》

作者: liqing151 | 来源:发表于2018-06-11 15:04 被阅读1次

    XML简介

      1. XML是半结构化的数据形式,在序列化程序数据用以在网络中进行传输的过程中非常有用。不是直接将程序中的结构化数据变为二进制数据,而是在结构化数据和半结构化数据的XML形式之间进行转化。然后使用预先定义的库在半结构化数据和二进制数据之间进行转换。
      1. XML中的标签是嵌套的,是栈的形式。
      1. Scala中可以直接以字面量的形式写XML文件。
      1. Scala中关于XML的主要类有ElemNode:所有XML节点类的抽象父类;Text:仅仅含有文字的节点;NodeSeq:处理节点的序列,在某些地方可能需要使用处理节点序列的方法来处理单个节点,这是可以的,Node继承自NodeSeq
      1. XML字面量中,可以使用{}进行转义来求解Scala代码的值。在{}不仅可以使用Scala code,也可以使用XML字面量来完成Node的嵌套。 xml.NodeSeq.Empty表示为空,nothing,什么都没有的XML节点。在{}<>以及&字符都会被转义。
    scala>  <a> {"</a>potential security hole<a>"} </a>
    res5: scala.xml.Elem = <a> &lt;/a&gt;potential security hole&lt;a&gt; </a>
    
      1. 不要使用String append的方式来构建XML,例如
    scala> "<a>" + "</a>potential security hole<a>" + "</a>"
    res5: String = <a></a>potential security hole<a></a>
    
      1. 程序员允许了用户在String中引入</a><a>来改变XML的结构,因此是不推荐使用添加字符串的形式来进行XML的扩建。

    序列化

    • 从程序中的结构化数据到XML的序列化,只需要使用XML字面量和{}进行转义计算表达式的值。如果需要在{}中包含{},则输入两个{}即可。
    def toXML =
    <cctherm>
    <description>{description}</description>
    <yearMade>{yearMade}</yearMade>
    <dateObtained>{dateObtained}</dateObtained>
    <bookPrice>{bookPrice}</bookPrice>
    <purchasePrice>{purchasePrice}</purchasePrice>
    <condition>{condition}</condition>
    </cctherm>
    
    scala> <a> {{{{brace yourself!}}}} </a>
    res7: scala.xml.Elem = <a> {{brace yourself!}} </a>
    

    反序列化

    • Scala中使用 XPath类似的语法来提取XML中的各个部分。
    提取tag之间的文字

    elem.text

    scala> <a> input ---&gt; output </a>.text
    res9: String = " input ---> output "
    
    提取子元素

    使用\方法,使用\\方法可以进行递归的子元素搜索。

    scala> <a><b><c>hello</c></b></a> \"a"
    res13: scala.xml.NodeSeq = NodeSeq()
    scala> <a><b><c>hello</c></b></a> \\"a"
    res14: scala.xml.NodeSeq =
    NodeSeq(<a><b><c>hello</c></b></a>)  //是可以包含自身
    
    提取属性

    使用\方法和\\方法,加入@符号

    scala> val joe = <employee name="Joe" rank="code monkey" serial="123"/>
    scala> joe \"@name"
    res17:  scala.xml.NodeSeq = Joe
    
    反序列化

    从上面的提取每个部分元素的方法对XML进行反序列化生成结构化的数据。


    XML和字节流之间的转换

      1. 最后一个转换:XML数据和字节流之间的转换。
      1. 最好使用库来进行XML的转换,可以确定字符编码,否则需要自己追踪字符的编码。
    将XML转换为字节数据:
    scala.xml.XML.save("therm1.xml", node)
    
    从字节数据中获取数据生成XML
    val loadnode = xml.XML.loadFile("therm1.xml") loadnode: scala.xml.Elem = ……
    
    • 这些都是基础的方法,还有许多针对不同读写流和输入输出流来序列化和反序列化XML的方法。

    模式匹配

    • XML使用模式匹配:模式看起来就像是XML字面量。最主要的区别是在{}中插入的代码不是一个表达式而是一个模式。
    匹配单个节点
    def proc(node: scala.xml.Node): String = node match {
    case <a>{contents}</a> => "It's an a: " + contents //这里的<a>与content之间的空格或者换行在node中有需要有强制性的匹配
    case <b>{contents}</b> => "It's a b: " + contents
    case _ => "It's something else."
    }
    可以匹配的XML为<a>It's a comment</a>,不能匹配的为<a><em>It's a comment</em></a>
    
    匹配一个节点序列,而不是单个节点
    def proc(node: scala.xml.Node): String = node match {
    case <a>{contents @ _*}</a> => "It's an a: " + contents
    case <b>{contents @ _*}</b> => "It's a b: " + contents
    case _ => "It's something else."
    }
    
    多次使用模式匹配,跳过空白字符
    • 使用变量绑定,将_*中的内容绑定到contents上。模式匹配可以用来跳过XML中的空白字符。
    val catalog =
      <catalog> //空白字符
        </cctherm>
           ……
        </cctherm>
        <cctherm>
            ……
       </cctherm>
     </catalog> // catalog中共有5个子节点,有3个空白字符节点,两个cctherm节点
    
    // 没有处理<catalog></catalog>前后的空白字符
    catalog match {
        case <catalog>{therms @ _*}</catalog> =>
            for (therm <- therms)
                println("processing: " +
                        (therm \"description").text)
    }
    //进一步使用模式匹配<cctherm>{_*}</cctherm生成for循环的迭代器。处理了空白字符
    catalog match {
        case <catalog>{therms @ _*}</catalog> =>
            for (therm @ <cctherm>{_*}</cctherm> <-
                         therms)
                println("processing: " +
                        (therm \"description").text)
    }
    

    相关文章

      网友评论

        本文标题:Chapter 28 《Working with XML》

        本文链接:https://www.haomeiwen.com/subject/hcpceftx.html