热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Scala处理XML文件(一)

Scala中处理XML文件的功能是比较强大的,因此不管怎样至少也得接触一下。XML也是Scala中的“第一类公民”,直接将一个XML格式的字符串赋值给一

Scala中处理XML文件的功能是比较强大的,因此不管怎样至少也得接触一下。XML也是Scala中的“第一类公民”,直接将一个XML格式的字符串赋值给一个val值变量就可以开始处理了。最基本的有scala.xml.Elem类中的 \ 方法和 \\ 方法,它们可用于直接对XML文件进行解析和提取。 

假如有如下的XML文件:

  1. <symbols> 
  2.     <symbol ticker="AAPL"> 
  3.         <units>200units> 
  4.     symbol> 
  5.      
  6.     <units>300units> 
  7.      
  8.     <symbol ticker="IBM"> 
  9.         <units>400units> 
  10.     symbol> 
  11. symbols> 

 

我们可以写一个Scala脚本来提取出其中的元素,顺便比较一下 \  \\ 方面的区别。脚本代码如下:

  1. val xmlFile = 
  2.      
  3.         ticker="AAPL"
  4.             200 
  5.          
  6.          
  7.         300 
  8.          
  9.         ticker="IBM"
  10.             400 
  11.          
  12.      
  13.  
  14. println(xmlFile)    // 直接打印xmlFragment的内容 
  15. println(xmlFile.getClass()) // 打印xmlFragment的类型 
  16.  
  17. val unitsNodes = xmlFile \ "units"  // 提取出元素 
  18. println(unitsNodes mkString "\n")   // 打印提取出的结果
  19. println(unitsNodes getClass)    // 打印symbolNodes的类型 




运行结果如下:

  1. <symbols> 
  2.         <symbol ticker="AAPL">  
  3.                 <units>200units> 
  4.         symbol>  
  5.   
  6.         <units>300units>  
  7.   
  8.         <symbol ticker="IBM">  
  9.                 <units>400units> 
  10.         symbol>  
  11. symbols> 
  12. class scala.xml.Elem 
  13. <units>300units> 
  14. class scala.xml.NodeSeq$$anon$1 

 

我们调用单反斜杠 \ 方法很简单地就提取出了xmlFile中的元素,并且打印出来的结果也跟源文件格式一致。但是,我们注意到提取出来的元素仅仅是当前节点下的元素,如果我们想要同时提取出xmlFile中嵌套在中的元素,此时应该使用双反斜杠 \\ 方法来代替上面脚本中的单反斜杠,修改如下:

  1. val unitsNodes = xmlFragment \\ "units" 

 执行结果如下:

 

  1. <units>200units> 
  2. <units>300units> 
  3. <units>400units> 
  4. class scala.xml.NodeSeq$$anon$1 

 

如果想要获取300中的数值300,则应该使用到Scala中的模式匹配,利用case语句来实现这一功能。假如我们针对上面使用了双反斜杠提取出来的unitsNodes,因为结果是一个数组,所以应该用unitsNodes(1)来获得对于300的引用,具体代码如下:




  1. unitsNodes(1) match { 
  2.       case <units>{numOfUnits}units> =>  
  3.              println("num of units : " + numOfUnits)  

 

注意,上面的{numOfUnits}中的花括号与><之间都不能存在空格。花括号里面是对之中值的引用。执行结果如下:

  1. num of units : 300  


当然,对于这样子简单的似乎没必要用一个模式匹配来实现,那么我们可以如下操作,调用NodeSeq类中的text()方法,如下:

  1. println(unitNodes(1).text)  


 执行结果与上面的一致,num of units : 300,只不过是对简单应用的简化方法而已。然而,我们把事情看得比较简单了,要是内还嵌套有其他元素对那怎么办?虽然使用上面的 text 方法同样能够提取出被嵌套的中的300(你可以试一下哦),但是你会发现打印出来是其格式有点儿不对劲,我想原因是在于层层的嵌套使得Scala对其解析之后的结果也以空格来表示了。

 

既然不能简单处理,那只能用回Scala中强大的模式匹配了。另外,如果我们想要同时提取出类似于中的ticker属性的值,也同样使用到了模式匹配。具体脚本如下:

  1. xmlFile match { 
  2.     case <symbols>{allSymbol @ _*}symbols> => 
  3.         for(symbolNode @ <symbol>{_*}symbol> <- allSymbol){ 
  4.             println("%-7s %s".format( 
  5.                 symbolNode \ "@ticker", (symbolNode \ "units").text))    
  6.         } 

 

在这里,{allSymbol @ _*} 中的@符号用于声明定义一个临时变量用来引用中的所有内容(即下划线加星号 _*,在这个例子中就是所有<symbol>…</symbol>元素对了),包括其他节点元素。

 

Scala的模式匹配case语句中,使用特殊符号@可以定义临时变量,例如for表达式,如下。真是强大啊!那么接下来的这一句:

  1. for(symbolNode @ <symbol>{_*}symbol> <- allSymbol) 

 中的symbolNode 也容易理解了,而 <- allSymbol 不就是 for 表达式中的迭代赋值吗?最后,println()中使用了正则表达式以及格式化输出format方法。

 

那么,for表达式中的symbolNode  allSymbols 是同样类型的(allSymbols迭代地赋值给symbolNode ),所以每一个 symbolNode 其实也就是每一个元素对了,看看文章最前面给出的XML文件,内是包含了 ticker 属性的,如下:

  1. <symbol ticker="AAPL">  
  2.         <units>200units>  
  3. symbol>  

  

那么我们使用symbolNode \ "@ticker" 这种格式将ticker属性的值提取出来。而接下来的(symbolNode \ "units").text 我们都知道是对当前的元素对往下找出元素对,再用text方法取出其值。


执行结果如下:


AAPL    200

IBM     400
 



推荐阅读
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • 开发笔记:实验7的文件读写操作
    本文介绍了使用C++的ofstream和ifstream类进行文件读写操作的方法,包括创建文件、写入文件和读取文件的过程。同时还介绍了如何判断文件是否成功打开和关闭文件的方法。通过本文的学习,读者可以了解如何在C++中进行文件读写操作。 ... [详细]
  • 本文详细介绍了GetModuleFileName函数的用法,该函数可以用于获取当前模块所在的路径,方便进行文件操作和读取配置信息。文章通过示例代码和详细的解释,帮助读者理解和使用该函数。同时,还提供了相关的API函数声明和说明。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • Go Cobra命令行工具入门教程
    本文介绍了Go语言实现的命令行工具Cobra的基本概念、安装方法和入门实践。Cobra被广泛应用于各种项目中,如Kubernetes、Hugo和Github CLI等。通过使用Cobra,我们可以快速创建命令行工具,适用于写测试脚本和各种服务的Admin CLI。文章还通过一个简单的demo演示了Cobra的使用方法。 ... [详细]
  • 怎么在PHP项目中实现一个HTTP断点续传功能发布时间:2021-01-1916:26:06来源:亿速云阅读:96作者:Le ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • IOS开发之短信发送与拨打电话的方法详解
    本文详细介绍了在IOS开发中实现短信发送和拨打电话的两种方式,一种是使用系统底层发送,虽然无法自定义短信内容和返回原应用,但是简单方便;另一种是使用第三方框架发送,需要导入MessageUI头文件,并遵守MFMessageComposeViewControllerDelegate协议,可以实现自定义短信内容和返回原应用的功能。 ... [详细]
  • 本文介绍了PHP常量的定义和使用方法,包括常量的命名规则、大小写敏感性、全局范围和标量数据的限制。同时还提到了应尽量避免定义resource常量,并给出了使用define()函数定义常量的示例。 ... [详细]
author-avatar
红星闪闪小肉肉
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有