欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Groovy解析生成标记语言XML HTML 博客分类: Groovy GroovyXMLHTMLJavaScriptSwing 

程序员文章站 2024-02-21 20:11:22
...
Groovy 把使用 XML 的美妙和简易性推向了极致,这就是 GroovyMarkup,它不仅简化了 SAX、DOM 操作,并且把这一理念引入到了 Swing、Swt 界面绘制领域中,Ant、Maven 构建脚本生成中;甚至铺散到更广阔的领域。
  • groovy.xml.MarkupBuilder  --  将你的对象序列化成 XML 或 XHTML
  • groovy.xml.SAXBuilder       --  可以用于现有的 SAX 处理器
  • groovy.xml.DOMBuilder     --  创建并解析 DOM 文档
  • groovy.util.AntBuilder        --  用来创建 Ant 构建文件
  • groovy.swing.SwingBuilder -- 用来创建 Swing 用户界面
  • groovy.util.NodeBuilder      --   创建一般的任意对象的树状结构

构建xml
def sw = new StringWriter();
def xml = new groovy.xml.MarkupBuilder(sw)
xml.langs(type:"current"){
  language(version:"1.6", flavor:"static", "java")
  language(version:"1.7", "groovy")
  language(version:"4", "javascript")
}
println sw


生成内容如下:
<langs type='current'>
  <language version='1.6' flavor='static'>java</language>
  <language version='1.7'>groovy</language>
  <language version='4'>javascript</language>
</langs>
1. MarkupBuilder 的默认构造是输出到控制台,还可以接受其他的参数 IndentPrinter、PrintWriter、Writer,分别指明了不同的输出目的地。所以你可以此控制输出到 Socket 上,或是 Groovlet 的网页上等。

2. MarkupBuilder 的方法名是想当然的,如这里的 langs()、language() 方法,它们会生成同名的标签。
3. 闭包中的方法生成为外层方法(标签) 的子标签,例如,上面的 language() 生成了 langs() 对应标签 <langs> 的子标签 <language>

通过 MarkupBuilder 构建 HTML
import groovy.xml.MarkupBuilder
def html = new MarkupBuilder()
html.html{
  head{
    title("Links")
  }
  body{
    h1("Here are my html bookmarks")
    table(border:"1"){
      tr{
        th("what")
        th("where")
      }
      tr{
        td("groovy articles")
        td{
          a(href:"http://ibm.com/developerworks", "DeveloperWorks")
        }
      }
    }
  }
}



MarkupBuilder 非常适合用于同步构建简单的 XML 文档。对于更加高级的 XML 创建,Groovy 提供了一个 StreamingMarkupBuilder。通过它,您可以添加各种各样的 XML 内容,比如说处理指令、名称空间和使用 mkp 帮助对象的未转义文本(非常适合 CDATA 块)
def comment = "<![CDATA[<!-- address is new to this release -->]]>"
def builder = new groovy.xml.StreamingMarkupBuilder()
builder.encoding = "UTF-8"
def person = {
  mkp.xmlDeclaration()
  mkp.pi("xml-stylesheet": "type='text/xsl' href='myfile.xslt'" )
  mkp.declareNamespace('':'http://myDefaultNamespace')
  mkp.declareNamespace('location':'http://someOtherNamespace')
  person(id:100){
    firstname("Jane")
    lastname("Doe")
    mkp.yieldUnescaped(comment)
    location.address("123 Main")
  }
}
def writer = new FileWriter("person.xml")
writer << builder.bind(person)



解析XML文件

<lang type="current">
    <language>java</language>
    <language>groovy</language>
    <language>javascript</language>
</lang>

def langs = new XmlParser().parse("language.xml")
println "type = ${langs.attribute("type")}"
langs.language.each{
  println it.text()
}


解析字符串变量XML
def xml = """
<langs type='current' count='3' mainstream='true'>
  <language flavor='static' version='1.5'>Java</language>
  <language flavor='dynamic' version='1.6.0'>Groovy</language>
  <language flavor='dynamic' version='1.9'>JavaScript</language>
</langs>
"""
def langs = new XmlParser().parseText(xml)
println "type = ${langs.attribute("type")}"
langs.language.each{
  println it.text()
}
println langs.getClass() // class groovy.util.Node 继承自ArrayList
println langs
println langs.attributes().each{
  println "-" * 15
  println it.key
  println it.value
}
def results = []
langs.language.each{
  results << it.text()
}
println results
def version = langs.language*.attribute("version")
println version


XmlParser 返回 Node 和 NodeList,XmlSlurper 返回一个 groovy.util.slurpersupport.GPathResult,不用调用attribute() text(),直接操作元素
def langs = new XmlSlurper().parseText(xml)
println langs.@count
langs.language.each{
  println it
}



groovy.util.NodeBuilder,用来创建一般任意对象的树状结构。看到了,它不在 groovy.xml 包之下,但它是一个 Builder,所以秉承了 Builder 的语法规则,而且还可用路径(对象导航)的方式来访问这个 Builder 实例中的节点或属性值。
import groovy.util.NodeBuilder;
someBuilder = new NodeBuilder();            //只有这么一个构建方法
root = someBuilder.users([balance:100]){    //这一块的语法完全同 MarkupBuilder
  user([gender:"male"],"xace");
  user("Joe"){
    order(item:"Book");
  }
}
// 因为 NodeBuilder 不预示着输出,所以需要显示的 print
println root;  
println("-----访问节点-----");
// get() 方法返回包含指定名称的所有子节点
// 就像 DOM 的 getElementsByTagName("user")
users = root.get("user");
// 用路径(导航)的方式访问节点 同users = root.user
users.each(){
  //用 name() 和 value() 分别访问节点的名称和值
  println "${it.name()}:${it.value()}";
}
println("-----访问属性-----");
// attributes() 方法返回节点属性的一个 Map
println root.attribute("balance");
println root.@balance;
println("-----深度优先遍历节点-----");
root.depthFirst().each(){
  println "${it.name()}:${it.attributes()}";
}
println("-----广度优先遍历节点-----");
root.breadthFirst().each(){
  println "${it.name()}:${it.value()}";
}
println("用 Java 迭代器来遍历一个节点的子节点");
it = root.iterator();
while(it.hasNext()){
  println it.next();
}