加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

温故知新: Groovy Recipes (下)

发布时间:2020-12-14 17:03:40 所属栏目:大数据 来源:网络整理
导读:7.4 Dealing with XML Attributes Using 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'

7.4 Dealing with XML Attributes

Using 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 sees the XML document as an ArrayList of nodes. This means
you have to use array notation all the way down the tree. XmlSlurper
sees the XML document as one big GPath query waiting to happen.

虽然有实现上的不同,但现在 XmlParser 和 XmlSlurper 已经越来越相像,基本上可以用前者的语法调用后者。

7.9 Parsing an XML Document with Namespaces

在处理命名空间时,XmlParser 与 XmlSlurper 的区别比较明显:XmlParser 严格遵守命名空间;而 XmlSlurper 则默认忽略命名空间,除非你进行了声明:

1: def p_xml = """http://somewhere.org/person"
   2: 

   
   

    
   3:     xmlns:p="
   4:     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   5:     xsi:schemaLocation="http://somewhere.org/person
   6:                         http://somewhere.org/person.xsd"
   7:     id="99" >
   8:   John
   9:   Smith
  10: 
  11: """http://somewhere.org/person" )
  12:? 
  13: def person = new XmlParser().parseText(p_xml)
  14: assert person.firstname == []
  15:? 
  16: def p = new groovy.xml.Namespace("
  17: //When dealing with namespaced elements,you can use only the HashMap notation
  18: println person[p.firstname].text()
  19:? 
  20: person = new XmlSlurper().parseText(p_xml)
  21: println person.firstname
  22: assert person.'p:firstname' == ''
  23:? 
  24: person.declareNamespace([p: 'http://somewhere.org/person'])
  25: println person.firstname
  26: println person.'p:firstname'

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

  • 前者为同步方法,会立即将结果输出到 stdout;后者为异步方法,在将 Builder 传递给 Writer 前,将不会产生文档,也不会有任何输出
  • 前者的输出经过简单的格式化,是“给人读的”,后者则是未经格式化的字符串。

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() }

动态语言的魔力啊。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读