iT邦幫忙

DAY 15
2

邊看邊學Groovy/Grails/Gradle系列 第 12

Groovy基本語法(6)-Parseing XML(1)-DOM

今天先跟大家分享Groovy如何處理DOM結構的文件,有兩條路,一條是引用原有的java API(javax.xml.parsers.DocumentBuilderFactory),當作對照組,另外一條路Groovy自行改寫過的groovy.xml.dom.DOMCategory,可以很直觀的處理DOM架構文件
首先,先把今天的XML po上來,這是我在寫Java FX2應用程式中其中一個FXML,存成XML作為今日範例:

<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.BorderPane?>

<BorderPane prefHeight="387.0" prefWidth="451.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="controller.RoutineCopyController">
  <!-- TODO Add Nodes -->
  <bottom>
    <Label alignment="CENTER" contentDisplay="CENTER" text="Copy Right By DNE I&C" BorderPane.alignment="CENTER" />
  </bottom>
  <center>
    <VBox alignment="CENTER" prefHeight="200.0" prefWidth="100.0" spacing="20.0">
      <children>
        <ProgressIndicator fx:id="progressIndicator" focusTraversable="false" prefHeight="132.0" prefWidth="475.0" progress="0.0" />
        <Label fx:id="copyMessage" prefHeight="34.0" prefWidth="4750" text="" />
        <Button fx:id="copyButton" mnemonicParsing="false" onAction="#beginCopy" text="Copy" />
      </children>
    </VBox>
  </center>
  <top>
    <Label alignment="CENTER" contentDisplay="CENTER" text="Daily Copy Program" textAlignment="CENTER" BorderPane.alignment="CENTER" />
  </top>
</BorderPane>

再來是沿用java API來讀出不同層的tag,範例如下:

import javax.xml.parsers.DocumentBuilderFactory
import static org.w3c.dom.Node.*

def factory=DocumentBuilderFactory.newInstance()
def builder=factory.newDocumentBuilder()
//建立Factory&Builder
def doc=builder.parse(new FileInputStream('D:\\groovy\\mygroovy\\src\\layout.xml'))
//讀入XML
def root=doc.documentElement //建立DOM Tree

String tagInfo(node){//定義一方法判斷及return對應的node文字
	switch(node.nodeType){//org.w3c.dom.node定義三種node
		case ELEMENT_NODE: //node名稱
			return "${node.nodeName}"
		case ATTRIBUTE_NODE://讀出屬性以及值
			return "Tag Attribute:${node.nodeName}=${node.nodeValue}" 
			
		case TEXT_NODE://這個沒看過,我只知道value,要再研究一下
			return "Tag Value: ${node.nodeValue}"
	}
	return "Some other type: ${node.nodeType}"
}

println "Root Tag ${tagInfo(root)}" //最上層
def subroot=root.childNodes.find{it.nodeName =='center'}
 //第二層,可用closure找到指定的tag
println "Tag:${tagInfo(root)}'s child is ${tagInfo(subroot)}" 
def vBox=subroot.childNodes.item(1) 
//第三層,除了用字串指定,也可以用index
println "Tag:${tagInfo(subroot)}'s child is ${tagInfo(vBox)}"
def vBoxAtt=vBox.attributes.getNamedItem('alignment') //讀出屬性以及值
println tagInfo(vBoxAtt)

執行結果:

Root Tag BorderPane
Tag:BorderPane's child is center
Tag:center's child is VBox
Tag Attribute:alignment=CENTER

第二種用Groovy把org.w3c.dom.Node相關處理寫成更直覺的DOMCategory class讓我們在處理DOM文件時可以直接用文件中的tag名稱存取資訊,範例如下

import groovy.xml.DOMBuilder 
import groovy.xml.dom.DOMCategory //配合DOMBuilder把org.w3c.dom.Node物件包裝更直觀

def doc=DOMBuilder.parse(new FileReader('D:\\groovy\\mygroovy\\src\\layout.xml'))
//DOMBuilder搭配的是FileReader,跟FileInputStream在這次的範例功能大同小異
def root=doc.documentElement
//建立DOM Tree

use(DOMCategory){ //使用DOMCategoy來處理{}內的statement
	println "Root Tag is ${root.name()}"
	println "Subroot Tag is ${root.center[0].name()}"
	println "${root.center[0].name()}'s child is ${root.center.VBox[0].name()}"
	println "${root.center.VBox[0].name()} has its child called "+ 
				"${root.center.VBox.children[0].name()}, "+  
				"and its grandchild called ${root.center.VBox.children.ProgressIndicator[0].name()}" 
}

執行結果:

Root Tag is BorderPane
Subroot Tag is center
center's child is VBox
VBox has its child called children, and its grandchild called ProgressIndicator

兩者相比,後者語法精簡很多,也更簡單的就可以存取到更深一層的tag


上一篇
Groovy基本語法(5)-使用Builder語法(Node, XML)
下一篇
Groovy基本語法(6)-Parseing XML(2)-using XmlParser/XmlSlurper
系列文
邊看邊學Groovy/Grails/Gradle27
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言