此示例假设你已经将如下的类放到你的CLASSPATH中:
XmlExamples.groovy
class XmlExamples { static def CAR_RECORDS = ''' <records> <car name='HSV Maloo' make='Holden' year='2006'> <country>Australia</country> <record type='speed'>Production Pickup Truck with speed of 271kph</record> </car> <car name='P50' make='Peel' year='1962'> <country>Isle of Man</country> <record type='size'>Smallest Street-Legal Car at 99cm wide and 59 kg in weight</record> </car> <car name='Royale' make='Bugatti' year='1931'> <country>France</country> <record type='price'>Most Valuable Car at $15 million</record> </car> </records> ''' }
此处是XmlSlurper用法的示例:
def records = new XmlSlurper().parseText(XmlExamples.CAR_RECORDS) def allRecords = records.car assert 3 == allRecords.size() def allNodes = records.depthFirst().collect{ it } assert 10 == allNodes.size() def firstRecord = records.car[0] assert 'car' == firstRecord.name() assert 'Holden' == firstRecord.@make.text() assert 'Australia' == firstRecord.country.text() def carsWith_e_InMake = records.car.findAll{ it.@make.text().contains('e') } assert carsWith_e_InMake.size() == 2 // alternative way to find cars with 'e' in make assert 2 == records.car.findAll{ it.@make =~ '.*e.*' }.size() // makes of cars that have an 's' followed by an 'a' in the country assert ['Holden', 'Peel'] == records.car.findAll{ it.country =~ '.*s.*a.*' }.@make.collect{ it.text() } def expectedRecordTypes = ['speed', 'size', 'price'] assert expectedRecordTypes == records.depthFirst().grep{ it.@type != '' }.'@type'*.text() assert expectedRecordTypes == records.'**'.grep{ it.@type != '' }.'@type'*.text() def countryOne = records.car[1].country assert 'Peel' == countryOne.parent().@make.text() assert 'Peel' == countryOne.'..'.@make.text() // names of cars with records sorted by year def sortedNames = records.car.list().sort{ it.@year.toInteger() }.'@name'*.text() assert ['Royale', 'P50', 'HSV Maloo'] == sortedNames assert ['Australia', 'Isle of Man'] == records.'**'.grep{ it.@type =~ 's.*' }*.parent().country*.text() assert 'co-re-co-re-co-re' == records.car.children().collect{ it.name()[0..1] }.join('-') assert 'co-re-co-re-co-re' == records.car.'*'.collect{ it.name()[0..1] }.join('-')
注意事项:
<foo> <foo-bar>test</foo-bar> </foo>
def foo = new XmlSlurper.parseText(FOO_XML) assert "test" == foo."foo-bar".text()
你也可以处理有命名空间的XML文档,如下:
def wsdl = ''' <definitions name="AgencyManagementService" xmlns:ns1="http://www.example.org/NS1" xmlns:ns2="http://www.example.org/NS2"> <ns1:message name="SomeRequest"> <ns1:part name="parameters" element="SomeReq" /> </ns1:message> <ns2:message name="SomeRequest"> <ns2:part name="parameters" element="SomeReq" /> </ns2:message> </definitions> ''' def xml = new XmlSlurper().parseText(wsdl).declareNamespace(ns1: 'http://www.example.org/NS1', ns2: 'http://www.example.org/NS2') println xml.'ns1:message'.'ns1:part'.size() println xml.'ns2:message'.'ns2:part'.size()
XmlSlurper的declareNamespace方法使用一个Map前缀来实现到URI的映射,你只需要声明命名空间并且在GPath表达式中使用此前缀即可,如下:
new XmlSlurper().parseText(blog).declareNamespace(dc: "http://purl.org/dc/elements/1.1/").channel.item.findAll { item -> d.any{entry -> item."dc:date".text() =~ entry.key} && a.any{entry -> item.tags.text() =~ entry }
一些备注:
你可以使用StreamingMarkupBuilder轻松的生成命名空间的元素:
System.out << new StreamingMarkupBuilder().bind { mkp.declareNamespace(dc: "http://purl.org/dc/elements/1.1/") root { dc.date() } }