温故知新: Groovy Recipes (下)
7.4 Dealing with XML AttributesUsing Hashmap Syntax for Attributes 1: def p = """" ssn="555-11-2222">John Smith""" 2: def person = new XmlParser().parseText(p) // or XmlSlurper 3: println person['@id'] 4: // ===> 99 5: ['id','ssn'].each { att -> println person["@$att"] } 6: // ===> 7: // 99 8: // 555-11-2222
7.8 Navigating Deeply Nested XML 1: def p = """""
2: " >
3: Jane
4: Doe
5: " >
6: 123 Main St
7: Denver
8: CO
9: 80020
10:
11: " >
12: 321 Tiam St
13: Denver
14: CO
15: 80020
16:
17: "
18:?
19: def person = new XmlParser().parseText(p) //person = new XmlSlurper().parseText(p) 20: println person.address.street[1].text()
21: println person.address[1].street.text()
22: println person.address.street.text()
虽然有实现上的不同,但现在 XmlParser 和 XmlSlurper 已经越来越相像,基本上可以用前者的语法调用后者。 7.9 Parsing an XML Document with Namespaces在处理命名空间时,XmlParser 与 XmlSlurper 的区别比较明显:XmlParser 严格遵守命名空间;而 XmlSlurper 则默认忽略命名空间,除非你进行了声明: 1: def p_xml = """http://somewhere.org/person"
2: 8.4 Creating Namespaced XML Using MarkupBuilder 1: def xml = new groovy.xml.MarkupBuilder()
2: def params = [:]
3: params.'xmlns:product' = 'urn:somecompany:products' 4: params.'xmlns:vendor' = 'urn:somecompany:vendors' 5: params.id = 99
6:?
7: xml.person(params) {
8: 'product:name'('iPhone') 9: 'vendor:name'('Apple') 10: quantity(1)
11: }
8.5 Understanding the Difference Between MarkupBuilder and StreamingMarkupBuilder
8.6 Creating Parts of the XML Document Separately 1: def builder = new groovy.xml.StreamingMarkupBuilder()
2: def person1 = {
3: person(id:99){
4: firstname('John') 5: lastname('Smith') 6: }
7: }
8:?
9: def comment = ' ' 10: def cdata = " >< & Look 'at' me & >< " 11: def person2 = {
12: person(id:100){
13: firstname('Jane') 14: lastname('Doe') 15: // Arbitrary Strings (Comments,CDATA) 16: unescaped << comment
17: unescaped << "${cdata}" 18: out << comment
19: // Or 20: mkp.yieldUnescaped(comment)
21: mkp.yield(comment)
22:
23: }
24: }
25: def personList = {
26: // XML Declaration 27: mkp.xmlDeclaration()
28: // Processing Instructions 29: mkp.pi('xml-stylesheet': "type='text/xsl' href='myfile.xslt'") 30: // Namespace 31: mkp.declareNamespace('': 'http://myDefaultNamespace') 32: mkp.declareNamespace('location': 'http://someOtherNamespace') 33: 'person-list' { 34: out << person1
35: out << person2
36: }
37: }
38:?
39: builder.encoding = 'UTF-8' 40: println builder.bind(personList)
41: // or new FileWriter('person.xml') << builder.bind(personList) 至此,简单的 XML 处理就都覆盖了。个人依然保持着对 XML 的无比厌恶……尤其是想到可以用 JSON 来代替网络数据交换这一点。到目前为止这本书没有对 XML (解析)性能浪费一点笔墨,如果你遇到一个两百兆的 XML 文件,是不是能用前述的方法解决就很难说了,但是——只要设计者脑子没有问题,我很难想出必须用巨大的 XML 文件的理由!而关于命名空间,我认为其纯属太空架构师试图赋予 XML 太多功能的结果。 8.13 Creating HTML on the Fly 1: new groovy.xml.MarkupBuilder().html {
2: head {
3: title('Search Results') 4: link(rel:'stylesheet',type:'text/css',href:'http://main.css') 5: script(type:'text/javascript',src:'http://main.js') 7: body {
8: h1('Search Results') 9: div(id:'results',class:'simple') { 10: table(border:1) {
11: tr {
12: th('Name') 13: th('Address') 14: }
15: tr {
16: td {
17: a(href:'http://abc.org?id=100','Jane Doe') 18: }
19: td('123 Main St') 20: }
21: }
22: }
24: }
9.3 Making an HTTP GET Request基本方式: 1: def page = new URL('http://www.aboutgroovy.com' ).text
2:?
3: new URL('http://www.aboutgroovy.com').eachLine { line -> 4: println line
5: }
7: 'http://www.aboutgroovy.com'.toURL().text Processing a Request Based on the HTTP Response Code 1: def url = new URL('http://www.aboutgroovy.com')
2: def connection = url.openConnection()
3: if(connection.responseCode == 200) { 4: println connection.content.text
5: } else { 6: println 'An error occurred:' 7: println connection.responseCode
8: println connection.responseMessage
9: }
9.5 Making an HTTP POST Request 1: def url = new URL('http://search.yahoo.com/search')
3: //switch the method to POST (GET is the default) 4: connection.setRequestMethod('POST') 5: //write the data 6: def queryString = 'n=20&vf=pdf&p=groovy+grails' 7: connection.doOutput = true
8: Writer writer = new OutputStreamWriter(connection.outputStream) 9: writer.write(queryString)
10: writer.flush()
11: writer.close()
12: connection.connect()
13: //print the results 14: println connection.content.text
PUT 和 DELETE 操作形式上同上。 RESTful POST Requests Using XML 1: def xml = """""
2:
3: Toyota
4: 2012
5: Prius
6: "
7: ...
8: connection.setRequestProperty('Content-Type','application/xml') 9: ...
10: writer.write(xml)
11: ...
10.1 Discovering the Class类的构造函数和实现的接口 1: println String.constructors
2: println String.interfaces
10.2 Discovering the Fields of a Class 1: def d = new Date()
2: // Calling getProperties() on a class returns a java.util.HashMap of all the fields 3: println d.properties
4: // getDeclaredFields() method that returns an array of java.lang.reflect.Field objects 5: // reflecting all the fields declared by the class or interface represented by this 6: // Class object. This includes public,protected,default (package) access,and private 7: // fields,but excludes inherited fields. 8: println Date.declaredFields
9: // MetaClass 10: println Date.metaClass
10.3 Checking for the Existence of a Field 1: class Person{
2: String firstname,lastname
3: }
4: def p = new Person() 5: // Will return the field,not a boolean value!! 6: println Person.metaClass.hasProperty(p,'firstname') 这个方法每次看到都想吐槽:典型的误导命名! 10.4 Discovering the Methods of a Class 1: Date.class.methods
2: Date.methods
3: Date.methods.name
10.5 Checking for the Existence of a Method 1: p.metaClass.respondsTo(p,'getFirstname')
10.7 Creating a Method Pointer 1: def list = []
2: def insert = list.&add
3: insert 'Java' 10.8 Calling Methods That Don't Exist (invokeMethod) 2: String name
3: Map relationships = [:]
4: Object invokeMethod(String what,Object who) {
5: if(relationships.containsKey(what)) 6: who.each { relationships.get(what) << it }
7: else 8: relationships.put(what,who as List)
9: }
10: }
11:?
12: def scott = new Person(name: 'Scott') 13: scott.married 'Kim' 14: scott.knows 'Ted','Ben' 15: scott.knows 'Jared' invokeMethod 可以说是 DSL 的基础,可以和 Scala 来比较下:形式上 Scala 的语法更自然(大多数时候没有 . 运算符),但论自由度 Groovy 则无疑胜出。 10.10 Adding Methods to a Class Dynamically (Categories) 1: use(RandomHelper) { //use(RandomHelper,InternetUtils,SomeOtherCategory) { ... }
2: 15.times{ println 10.rand() }
4:?
5: class RandomHelper{ 6: static r = new Random() 7: static int rand(Integer self){ 8: r.nextInt(self.intValue())
10: }
10.11 Adding Methods to a Class Dynamically (ExpandoMetaClass) 1: Integer.metaClass.rand = { new Random().nextInt(delegate.intValue()) }
2: 15.times { println 10.rand() }
动态语言的魔力啊。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |