在Groovy語言中,Gpath可能是我們最常用的一種功能了。當然了,我們使用Gpath大多用在對 GroovyBean對象的操作上。其實,除了操作GroovyBean對象,Gpath還用在對XML文檔的操作上。即使是 用於對GroovyBean對象的操作,我們也未必對Gpath的使用知之甚詳,所以我們這篇就來詳細說說Gpath 。
首先,Gpath用到對類的屬性的操作上,是用於對對象屬性的訪問,形如:“對象.屬性”的訪問方式 。比如,我們有如下的兩個GroovyBean:
class Address
{
String prov
String city
}
class Person
{
String id
String name
Address addr
}
現在,我們就可以使用Gpath來操作它們:
def addr = new Address(prov:'Hubei',city:'Xiaogan')
def person = new Person(id:123,name:'Wallace',addr:addr)
println person.name
println person.addr.city
運行結果為:
WallaceXiaogan
可以看到“person.name”訪問的是對象“person”的屬性“name”,而“person.addr.city”則是 先訪問“person”的屬性“addr”,然後再訪問“addr”的屬性“city”。通過這樣的一種訪問方式, 使得這種類的組合方式不論嵌套多少層,都可以使用Gpath訪問得到。
值得注意的是,上面的嵌套訪問並不是安全的。請看下面的例子:
def person = new Person(id:123,name:'Wallace')
println person.addr.city
這樣的訪問就會報空指針的錯誤。為了解決這種空指針的錯誤,在Java語言中通常要做如下的非空 判斷:
if(person!=null&&person.addr!=null)
{
println person.addr.city
}
而在Groovy語言中則無需這麼麻煩,我們只需要使用“?.”操作符即可,它的結果是如果Gpath訪問 的對象存在,則返回結果;否則返回null。請看下面的例子:
def person = new Person(id:123,name:'Wallace')
println person?.addr?.city
運行結果為:
null
其次,如果是對XML文檔的訪問,則“a.b.c”代表的是節點“<a>”中包含節點“<b>” , 節點“<b>”中包含節點“<c>”,即形如下面的樣子:
<a>
<b>
<c>…</c>
</b>
</a>
下面,我們來看一個實際的例子:
def text = """
<persons>
<person sex='male'>
<id>1</id>
<name>Tom</name>
</person>
<person sex='female'>
<id>2</id>
<name>Alice</name>
</person>
</persons>
"""
def node = new XmlSlurper().parseText(text)
node.person.each{
println it.name
}
}
運行結果為:
TomAlice
可以看到,變量“node”是XML文檔的根節點,即“persons”節點。而節點“node.person”存在多 個節點,所以要進行循環,然後再一次往下數節點即可。
跟GroovyBean對象的Gpath訪問比起來,除了Gpath對XML的訪問會遇到多節點以外,Gpath對XML的訪 問不會存在空指針的情況。請看下面的例子:
println node.p.x
運行結果是打印空行。可以看出,如果XML的節點不存在,那麼返回的是空字符串。
還有需要注意的是:使用Gpath訪問GroovyBean對象的屬性並不是直接訪問該屬性,而是通過“set” 和“get”方法進行的。請看下面的例子:
class Person
{
String id
String name
Address addr
def getName()
{
return 'Tom'
}
}
在上面的“Person”類中,我們自己定義了“getName”方法,讓它永遠返回“Tom”,下面,我們使 用Gpath來測試它:
def person = new Person(id:123,name:'Wallace')
println person.name
運行結果為:
Tom
由於我們在“person”對象的定義中設置了“name”屬性的值為“Wallace”,很明顯,“person” 對象的“name”屬性值為“Wallace”,但我們使用“person.name”訪問的返回值只能是“Tom”,因為 方法“getName”永遠返回“Tom”。
當然,我們也有辦法訪問屬性的真實值,這就是使用“.@”操作符。請看下面的例子:
def person = new Person(id:123,name:'Wallace')
println person.name
println person.@name
運行結果為:
TomWallace
當然了,上面的情況又是通過Gpath訪問GroovyBean對象的特殊情況,在通過Gpath訪問XML的時候不 會存在上面的情況。但是,在通過Gpath訪問XML的時候,“.@”操作符也有它自己的用途。請看下面的 例子:
def text = """
<persons>
<person sex='male'>
<id>1</id>
<name>Tom</name>
</person>
<person sex='female'>
<id>2</id>
<name>Alice</name>
</person>
</persons>
"""
def node = new XmlSlurper().parseText(text)
node.person.each{
println it.@sex
}
運行結果為:
malefemale
可以看出,使用“.@”操作符可以訪問一個節點的屬性。
說到這裡,總算是對Gpath做了一個全面的、基本的交代。為什麼說是一個基本的交代呢?其實就在 於使用Gpath訪問XML還有很多的內容,在這裡不能一一交代了。請大家在用到的時候查閱相關的文檔。