初试Scala解析XML
使用Scala解析XML,充分体现了函数式编程的特点,简洁和明了。用Java去解析不是不行,只不过代码不够清晰明了。
首先先把XML文件读入到内存里:
val someXml = XML.loadFile("file/FIXExample.xml")
这样someXml是一个scala.xml.Elem对象。
Scala XML API提供了类似XPath的语法来解析XML。在NodeSeq这类父类里,定义了两个很重要的操作符("\"和"\\"),用来获得解析XML:
- \ :Projection function, which returns elements of this sequence based on the string that--简单来说,\ 根据条件搜索下一子节点
- \\:Projection function, which returns elements of this sequence and of all its subsequences, based on the string that--而 \\ 则是根据条件搜索所有的子节点
先上一个XML的文件作为例子:
<fix major="4" minor="2">
<header>
<field name="BeginString" required="Y">FIX4.2</field>
<field name="MsgType" required="Y">Test</field>
</header>
<trailer>
<field name="Signature" required="N"/>
<field name="CheckSum" required="Y"/>
</trailer>
<messages>
<message name="Logon" msgtype="A" msgcat="admin">
<field name="ResetSeqNumFlag" required="N"/>
<field name="MaxMessageSize" required="N"/>
<group name="NoMsgTypes" required="N">
<field name="RefMsgType" required="N"/>
<field name="MsgDirection" required="N"/>
</group>
</message>
<message name="ResendRequest" msgtype="2" msgcat="admin">
<field name="BeginSeqNo" required="Y"/>
<field name="EndSeqNo" required="Y"/>
</message>
</messages>
<fields>
<field number="1" name="TradingEntityId" type="STRING"/>
<field number="4" name="AdvSide" type="STRING">
<value enum="X" description="CROSS"/>
<value enum="T" description="TRADE"/>
</field>
<field number="5" name="AdvTransType" type="STRING">
<value enum="N" description="NEW"/>
</field>
</fields>
</fix>
1. 首先来个简单的,如果要找header下的field,那么这样写即可:
val headerField = someXml\"header"\"field"
2.找所有的field:
val field = someXml\\"field"
3. 找特定的属性(attribute),如找header下的所有field的name属性的值:
val fieldAttributes = (someXml\"header"\"field").map(_\"@name") val fieldAttributes = someXml\"header"\"field"\\"@name"
两个都能找到header下面所有field的name属性,但问题是输出的格式不一样。前者会返回一个List-List(BeginString, MsgType),而后者仅仅是BeginStringMsgType。中间连空格也没有。所以建议用前一种方法获得属性。
之前以为,下面的方法,和第二种方法一样能够获得属性的值:
val fieldAttributes = someXml\"header"\"field"\"@name"
根据\操作符的定义,理论上应该可以输出name属性的。实际上输出的结果是空,什么也没有。
\操作符的源码里有这么一段:
that match {
case "" => fail
case "_" => makeSeq(!_.isAtom)
case _ if (that() == '@' && this.length == ) => atResult
case _ => makeSeq(_.label == that)
}
第三个case表面,只有当this.length==1时,才可以这样做。原因其实很简单,somXml\"header"\"field"返回的是一个Seq[Node]的集合,包含多个对象。而\"@"的操作无法确定操作哪一个对象的属性:
val x = <b><h id="bla"/><h id="blub"/></b>
val y = <b><h id="bla"/></b>
println(x\\"h"\"@id") //Wrong
println(y\\"h"\"@id") //Correct with output: bla
4. 查找并输出属性值和节点值的映射:
(someXml\"header"\"field").map(n=>(n\"@name", n.text, n\"@required"))
这样的输出是List((BeginString,FIX4.2,Y), (MsgType,Test,Y))
5. 有条件地查找节点,例如查找name=Logon的message:
val resultXml1 = (someXml\\"message").filter(_.attribute("name").exists(_.text.equals("Logon")))
val resultXml2 = (someXml\\"message").filter(x=>((x\"@name").text)=="Logon")
6. 通过 \\"_" 获得所有的子节点,例如:
println(resultXml1\\"_")
结果是:
<message msgcat="admin" msgtype="A" name="Logon">
<field required="N" name="ResetSeqNumFlag"/>
<field required="N" name="MaxMessageSize"/>
<group required="N" name="NoMsgTypes">
<field required="N" name="RefMsgType"/>
<field required="N" name="MsgDirection"/>
</group>
</message>
<field required="N" name="ResetSeqNumFlag"/>
<field required="N" name="MaxMessageSize"/>
<group required="N" name="NoMsgTypes">
<field required="N" name="RefMsgType"/>
<field required="N" name="MsgDirection"/>
</group>
<field required="N" name="RefMsgType"/>
<field required="N" name="MsgDirection"/>
本文完
初试Scala解析XML的更多相关文章
- Scala入门到精通——第二十七节 Scala操纵XML
本节主要内容 XML 字面量 XML内容提取 XML对象序列化及反序列化 XML文件读取与保存 XML模式匹配 1. XML 字面量 XML是一种很重要的半结构化数据表示方式,眼下大量的应用依赖于XM ...
- Android 解析XML文件和生成XML文件
解析XML文件 public static void initXML(Context context) { //can't create in /data/media/0 because permis ...
- Android之解析XML
1.XML:可扩展标记语言. 可扩展标记语言是一种很像超文本标记语言的标记语言. 它的设计宗旨是传输数据,而不是显示数据. 它的标记没有被预定义.需要自行定义标签. 它被设计为具有自我描述性. 是W3 ...
- Android之Pull解析XML
一.Pull解析方法介绍 除了可以使用SAX和DOM解析XML文件,也可以使用Android内置的Pull解析器解析XML文件.Pull解析器的运行方式与SAX解析器相似.它也是事件触发的.Pull解 ...
- Android之DOM解析XML
一.DOM解析方法介绍 DOM是基于树形结构的节点或信息片段的集合,允许开发人员使用DOM API遍历XML树,检索所需数据.分析该结构通常需要加载整个文档和构造树形结构,然后才可以检索和更新节点信息 ...
- Android之SAX解析XML
一.SAX解析方法介绍 SAX(Simple API for XML)是一个解析速度快并且占用内存少的XML解析器,非常适合用于Android等移动设备. SAX解析器是一种基于事件的解析器,事件驱动 ...
- Android 使用pull,sax解析xml
pull解析xml文件 1.获得XmlpullParser类的引用 这里有两种方法 //解析器工厂 XmlPullParserFactory factory=XmlPullParserFactory. ...
- 用 ElementTree 在 Python 中解析 XML
用 ElementTree 在 Python 中解析 XML 原文: http://eli.thegreenplace.net/2012/03/15/processing-xml-in-python- ...
- java解析xml的三种方法
java解析XML的三种方法 1.SAX事件解析 package com.wzh.sax; import org.xml.sax.Attributes; import org.xml.sax.SAXE ...
随机推荐
- rabbitmq性能优化之Consumer utilisation
如下所示,每个rabbitmq队列除了发布和消费吞吐量外,还有一个评价MQ队列效率的更加重要的指标Consumer utilisation ,如下: 在最佳利用率情况下,这个值能够达到100%,并且生 ...
- 000.Introduction to ASP.NET Core--【Asp.net core 介绍】
Introduction to ASP.NET Core Asp.net core 介绍 270 of 282 people found this helpful By Daniel Roth, Ri ...
- 程序员用HTML5制作的爱心树表白动画
体验效果:http://keleyi.com/keleyi/phtml/html5/31.htm 推荐:http://hovertree.com/texiao/css3/18/ HTML代码如下: & ...
- JS+HTML5的Canvas画图模拟太阳系运转
查看效果:http://hovertree.com/texiao/html5/9.htm 地球自传 http://hovertree.com/texiao/html5/8.htm 代码如下: < ...
- kmdjs指令大全
调试 通过下面方式,可以输出kmdjs声称的类: <script src="../dist/kmd.js?debug" data-main="js/main&quo ...
- 设置statusBarStyle
设置状态栏的样式, typedef NS_ENUM(NSInteger, UIStatusBarStyle) { UIStatusBarStyleDefault ...
- [Android]官网《UI/Application Exerciser Monkey》中文翻译
以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/5049041.html 翻译自 Android Develope ...
- jQuery初探 jQuery选取和操纵元素的特点
jQuery初探 jQuery选取和操纵元素的特点 JavaScript选取元素 先来看看不用jQuery的时候我们是怎么处理元素选取的. JavaScript选取元素的时候,可以根据id获取元素,当 ...
- MVC缺点
MVC的不足之处表现在以下几个方面: (1) 增加了系统结构和实现的复杂性.对于简单的界面,严格遵循MVC,使模型.视图与控制器分离,会增加结构的复杂性,并可能产生过多的更新操作,降低运行效率. (2 ...
- AES 加密工具类
/** * AES 是一种可逆加密算法,对用户的敏感信息加密处理 对原始数据进行AES加密后,在进行Base64编码转化: */public class AESOperator { /* * 加密用的 ...