zoukankan      html  css  js  c++  java
  • 快学Scala(16)--XML处理

    读取,分析,创建和编写xml

    1. XML字面量

    val doc = <html><head><title>Fred's Memoir's</title></head><body>...</body></html>  //scala.xml.Elem
    val items = <li>Fred</li><li>Wilma</li>  //scala.xml.NodeSeq
    

      注:有时,编译器会错误地识别出XML,例如x <y就会被理解为未结束的XML字面量

    2. XML节点

    Node类是所有XML节点类型的祖先。它的两个最重要的子类是Text和Elem。

      def main(args: Array[String]): Unit = {
        val elem = <a href = "http://scala-lang.org">The <em>Scala</em>language</a>
        for(n <- elem.child) {
          println(n)
        }
      }
    

      上述程序的输出结果为:

     

      可以看出elem节点序列

        val items = new NodeBuffer
        items += <li>Fred</li>
        items += <li>Wilma</li>
        val nodes: NodeSeq = items

    有三个字节点,分别是两个Text节点和一个Elem节点。

    3. 元素属性

    要处理某个元素的属性键和值,可以用attributes属性。它将产出一个类型为MetaData的对象,该对象几乎就是但又不完全等同于一个从属性键到属性值的映射。你可以用()操作符来访问给定键的值。

    val elem = <a href="http://scala-lang.org/">The Scala Language</a>
    val url = elem.attributes("href")
    

      

    val elem = <a href = "http://scala-lang.org">The <em>Scala</em> language</a>
    val url = elem.attributes.get("href").getOrElse(Text(""))
    for(attr <- elem.attributes) printf("attr.key: %s, attr.value.text: %s
    ", attr.key, attr.value.text)
    

      输出结果为: attr.key: href, attr.value.text: http://scala-lang.org

    val image = <img alt="TODO" src ="hamster.jpg"/>
    val map = image.attributes.asAttrMap
    for(key <- map.keys) printf("key: %s, value: %s
    ", key, map.get(key))
    

      

    4. 内嵌表达式

    你可以在XML字面量中包含Scala代码,动态的计算出元素内容

    <ul><li>{items(0)}</li><li>{items(1)}</li></ul>
    <ul>{for (i <- items) yield <li>{i}</li>}</ul>

      

    5. 在属性中使用表达式

    <img src={makeURL(filename)}/>

    注:被引用的字符串当中的花括号不会被解析和求值,例如<img src=“{makeURL(filename)}”/>将src属性设置为字符串“{makeURL(filename)}”。

    如果内嵌代码块返回null或None,则该属性不会被设置

    6. 特殊节点类型

        val js = <script><![CDATA[if (temp) < 0 alert("Cold")]]></script>
    
        val code = """if (temp < 0) alert ("Cold")"""
        val js1 = <script>{PCData(code)}</script>
    

      

        val g1 = <xml:group><li>Item 1</li><li>Item 2</li></xml:group>
        val g2 = Group(Seq(<li>Item 1</li>, <li>Item 2</li>))
        println(g2)
    

      输出结果为: <li>Item 1</li><li>Item 2</li>

    7. 类XPath表达式

    操作符定位某个节点或节点序列的直接后代

        val list = <dl><dt>Java</dt><dd>Gosling</dd><dt>Scala</dt><dd>Odersky</dd></dl>
        val languages = list  "dt"
        for(item <- languages) println(item)
    

      输出结果为: 

    <dt>Java</dt>
    <dt>Scala</dt>

    通配符可以匹配任何元素

        val list = <ds><dl><dt>Java</dt><dd>Gosling</dd><dt>Scala</dt><dd>Odersky</dd></dl></ds>
        val languages = list "_"  "dt"
        for(item <- languages) println(item)
    

    \可以定位任何深度的后代

    以@开头的字符串可以定位属性 img "@alt"将返回给定节点的alt属性,img \ "@alt"将定位到img中任何元素的所有alt属性。但是不能使用通配符。

    8. 模式匹配

    node match {
      case <img/> => ...
      ...
    }
    

      如果node是一个带有任何属性但没有后代的img元素,则第一个匹配会成功。

      处理单个后代的匹配表达式 case <li>{_}</li> => ...

      处理多个后代的匹配表达式 case <li>{_*}</li> => ...

    除了使用通配符,也可以使用变量名。成功匹配到的内容会被绑定到该变量上

    case <li>{child}</li> => child.text

    要匹配一个文本节点,可以用如下这样的样例类匹配:  case <li>{Text(item)}</li> => item

    要把节点序列绑到变量,使用如下语法:  case <li>{children @_*}</li> => for (c <- children) yield c

    若要匹配到属性,得用守卫:  case n @ <img/> if (n.attributes("alt").text == "TODO") => ...

    9. 修改元素和属性

    val list = <ul><li>Fred</li><li>Wilma</li></ul>
    val list2 = list.copy(label = "ol")
    val list3 = list.copy(child = list.child ++ <li>Another item</li>)
    println(list2)
    println(list3)

    输出结果为:   

    <ol><li>Fred</li><li>Wilma</li></ol>
    <ul><li>Fred</li><li>Wilma</li><li>Another item</li></ul>

    要添加或删除属性,可以用%操作符

    val image = <img src="hamster.jpg"/>
    val image2 = image % Attribute(null, "alt", "An image of a hamster", Attribute(null, "val", "frog.jpg", Null))
    println(image2)
    

      输出结果为:<img val="frog.jpg" alt="An image of a hamster" src="hamster.jpg"/>

    10. XML变换

      def main(args: Array[String]): Unit = {
        val root = <ul><li>Fred</li><li>Wilma</li></ul>
        val rule1 = new RewriteRule {
          override def transform(n: Node): Seq[Node] = {
            case e @ <ul>{_*}</ul> => e.asInstanceOf[Elem].copy(label = "ol")
            case _ => n
          }
        }
        val transformed = new RuleTransformer(rule1).transform(root)
      }
    

      可以在RuleTransformer的构造器中给出多个规则:

    val transformer = new RuleTransformer(rule1, rule2, rule3)
    

      

    11. 加载和保存

    import scala.xml.XML
    val root = XML.loadFile("myfile.xml")
    val root2 = XML.load(new FileInputStream("myfile.xml"))
    val root3 = XML.load(new InputStreamReader(new FileInpurStream("myfile.xml"), "UTF-8"))
    val root4 = XML.load(new URL("http://horstmann.com/index.html"))

      注:文档是使用Java类库中标准的SAX解析器加载的。但可惜并没有提供文档类型的定义。

    要保存XML到文件中,可以用sava方法。

    XML.save("myfile.xml", root)
    

      有三个可选参数:

    • enc用来指定字符编码(缺省为"ISO-8859-1")
    • xmlDecl用来指定输出中最开始是否要生成XML声明(<?xml...?>)(缺省为false)
    • doctype是样例类scala.xml.dtd.DocType的对象(缺省为null)

    也可以保存到java.io.Writer,但是必须给出所有参数

    XML.write(writer, root, "UTF-8", false, null)
    

      

    12. 命名空间

    xmlns属性可以声明一个命名空间

  • 相关阅读:
    基于 OAI 部署私有的 4G EPS
    Ubuntu Snap 简述
    OAI SDR LTE 基站部署
    企业文化二三谈
    OpenStack 的 SR-IOV 虚拟机热迁移
    在 ThinkPad E470 上安装 Ubuntu 16.04 无线网卡驱动
    读写可编程 SIM/USIM 卡
    4G LTE/EPC UE 的附着与去附着
    4G EPS 的网络协议栈
    Java- 类型转换
  • 原文地址:https://www.cnblogs.com/PaulingZhou/p/6690359.html
Copyright © 2011-2022 走看看