十九、XML解析
groovy中也是存在数据解析的。比如xml,gson等等解析数据。groovy中的xml解析使用MarkupBuilder对象。下面是一个生成一段xml的例子:
def mB = new MarkupBuilder()
mB.collection(aaaaa: '开始解析了') {
movie(title: 'Enemy Behind')
type('War, Thriller')
format('DVD')
year('2003')
rating('PG')
stars(10)
hello('你好呀!!')
description('Talk about a US-Japan war')
执行结果显示:
<collection aaaaa='开始解析了'>
<movie title='Enemy Behind' />
<type>War, Thriller</type>
<format>DVD</format>
<year>2003</year>
<rating>PG</rating>
<stars>10</stars>
<hello>你好呀!!</hello>
<description>Talk about a US-Japan war</description>
</collection>
- .collection():用于创建 </ collection>的头XML标签,固定开头。
- movie(title:"****"):创建一个名称为movie的标签,并且指定一个名为title的值,这实际上表示需要为该元素创建一个属性。
- format、year、hello等:都是创建对应名称的标签,括号里面是该标签的值。标签名与值可以是任意命名。
groovy也可以将一段编写好的xml解析出来。解析Xml使用XmlParser对象。这是一份存放在本地盘下的moves.xml文件:
<collection shelf = 'New Arrivals'>
<movie title = 'Enemy Behind'>
<type>War, Thriller</type>
<year>2003</year>
</movie>
<movie title = 'Transformers'>
<type>Anime, Science Fiction</type>
<year>1989</year>
</movie>
<movie title = 'Trigun'>
<type>Anime, Action</type>
<year>1986</year>
</movie>
<movie title = 'Ishtar'>
<type>Comedy</type>
<year>1987</year>
</movie>
</collection>
解析代码:
def par = new XmlParser()
def doc = par.parse("E:moves.xml")
doc.movie.each { //movie 为xml的一个子标签,没有提示写起来很不友好
mv ->
print("Movie Tittle=")
println "${mv['@title']}"
print("Movie Type=")
println "${mv.type[0].text()}"
print("Movie year=")
println "${mv.year[0].text()}"
println("*******************************")
}
- doc.movie: 将文件下的所有标签作为了节点列表,可以通过遍历去访问属性跟子标签(子节点)内容。
- mv[’@title’] :使用@符号访问附加到movie标签的title属性。
- mv.type[0].text() : 输出movie标签下的type子元素的text值。没有提示写起来不是很友好
输出结果:
Movie Tittle=Enemy Behind
Movie Type=War, Thriller
Movie year=2003
'******************************* ’
Movie Tittle=Transformers
Movie Type=Anime, Science Fiction
Movie year=1989
'******************************* ’
Movie Tittle=Trigun
Movie Type=Anime, Action
Movie year=1986
'******************************* ’
Movie Tittle=Ishtar
Movie Type=Comedy
Movie year=1987
‘*******************************’
二十、Json解析
groovy实现json解析需要用到JsonSlurper类。
1、文本解析
def jsonSlurper = new JsonSlurper()
def object = jsonSlurper.parseText('{ "name": "John", "ID" : "1"}')
println object.name
println object.ID
通过jsonSlurper.parseText就可以将json文本解析成相应的对象了。下面解析一个稍微复杂一点的json文本:
def strs = '{"id":"1","name":"jack","likes":[{"food":"apple","sport":"swimming","book":"ABCD"}]}'
def person = jsonSlurper.parseText(strs)
println person.id
println person.name
println person.likes
person.likes.each{
like ->
println like.food
println like.sport
println like.book
}
//运行结果:
/**
* 1
* jack
* [[food:apple, sport:swimming, book:ABCD]]
* apple
* swimming
* ABCD
*/
2、解析成json字符串
将对象解析成json使用JsonOutput类。
def list = [name: 'John', ID: 1]
def output = JsonOutput.toJson()
println(output);
// 输出结果:{"name":"John","ID":1}
A apple = new Apple("红色","150g")
println JsonOutput.toJson(apple)
// 输出结果:{"color":"\u7ea2\u8272","weight":"150g"}
二十一、模板引擎
所谓的模板引擎其实是通过使用占位符建立模板,然后使用动态数据替换掉占位符的专门的类。有时候一大串内容会需要重复应用到多个地方,但是内容相差又不大。这时使用模板引擎就会很方便了。
def str3 = "1000000000000"
println "我有${str3}元"
上面就是一个最简单字符串模板。几种常用的简单模板引擎:
- SimpleTemplateEngine : 需要绑定参数列表及其值,以便在有定义占位符的字符串中替换它们。也适用于xml。
- StreamingTemplateEngine :跟SimpleTemplateEngine相似,可以使用可写的闭包创建模板,使其对于大模板更具可扩展性。也适用于xml。特别是这个模板引擎可以处理大于64k的字符串。
- XMLTemplateEngine :如同名称一样,模板源跟输出结果都是xml。
def modle = '你好呀,我$age 岁,来自$countray'
def binding = ['age': 18, 'countray': '意大利亚']
// 初始化引擎
def engine = new SimpleTemplateEngine()
def text = engine.createTemplate(modle).make(binding)
println text
//输出结果:
// 你好呀,我18 岁,来自意大利亚
下面是一个SimpleTemplateEngine用在xml的例子。本项目下有个xml文件,使用了三个占位符name,id,subject标记。
<Student>
<name>${name}</name>
<ID>${id}</ID>
<subject>${subject}</subject>
</Student>
groovy实现代码:
ef file = new File("D:/Student.template")
def binding = ['name' : 'Joe', 'id' : 1, 'subject' : 'Physics']
def engine = new SimpleTemplateEngine()
def template = engine.createTemplate(file)
println template.make(binding)
//打印结果,已经将所有的占位符全部替换成了目标数据:
<Student>
<name>Joe</name>
<ID>1</ID>
<subject>Physics</subject>
</Student>
二十二、元对象编程
什么是元对象编程呢?正常情况下,我们定义了一个类。如果我们没有先定义好指定的属性或者方法而去使用那个属性或者调用那个方法时,程序
肯定无法通过编译(或者运行异常)。而当使用元对象编程呢就不会出现这些情况。可以使用未定义的属性或者调用方法但是程序却不会抛出异常来。
要是用元对象编程需要让类实现一个GroovyInterceptable接口。
先创建一个类,什么方法,属性都不写:
class Metaobject{
}
然后去调用它的为定义的属性或者方法:
Metaobject mj = new Metaobject()
mj.name = "小明"
mj.call()
println mj.name
这样子肯定是会抛出异常的。下面使用元编程模式:
class Metaobject implements GroovyInterceptable {
protected aaa = [:]
void setProperty(String pName, val) {
aaa[pName] = val
}
def getProperty(String pName) {
aaa[pName]
}
def methodMissing(String name, def args) {
println "Missing method"
}
def invokeMethod(String name, Object args) {
return "called invokeMethod"
}
实现了 GroovyInterceptable接口,添加了一个aaa的Map,get、set方法。注意setProperty(),getProperty(),invokeMethod()都是接口里面定义方法。并且做到这样子再去运行程序就不会抛出异常了。
1、缺失属性:
使用没有定义出来的属性被称之为缺失属性。在元编程下,程序可以正常运行,需要有一个Map变量(例子中的aaa),用于保存即时创建的成员变量的值。然后实现getproperty()和setproperty(),在运行时获取和设置类的属性的值。
2、缺失方法:
使用没有先定义的方法被称之为缺失方法。缺失方法元编程需要实现invokeMethod()方法。之后调用未定义的方法(例子中的call())程序便不会抛出异常。
3、方法缺失:
在使用为定义方法下,还可实现methodMissing() 这个方法从而达到是使程序正常运行的目的。第2点提到的invokeMethod()类似,但是优先级低于invokeMethod(),它仅在失败的方法分派的情况下被调用。在例子中,最终结果不会有 "Missing method"的输出。当不实现invokeMethod才会有输出结果。
参考资料: W3Cschool Groovy教学