使用Digester解析XML文件的三種方式小結(jié)
1. Digester解析XML文件的三種方式
作用及依賴jar包
首先明白Digester是干什么的?它是apache開源項(xiàng)目Commons中的一個(gè)子項(xiàng)目,用于解析XML文檔的工具。Digester底層采用的是SAX解析方式,通過遍歷XML文檔規(guī)則來(lái)進(jìn)行處理。項(xiàng)目中有需要將XML文件中的信息解析為我們需要的內(nèi)容時(shí)(如java類),使用Digester是非常方便的。話不多說(shuō),本案例使用的jdk版本是1.6。簡(jiǎn)單的jar包依賴如下:
- commons-digester-1.8.jar
- commons-logging.jar
- commons-collections-3.2.1.jar
- commons-beanutils-1.7.0.jar
2. 重點(diǎn)和難點(diǎn)
重點(diǎn):理解棧的概念
難點(diǎn):當(dāng)使用addObjectCreate()方法時(shí),會(huì)創(chuàng)建一個(gè)對(duì)象進(jìn)棧,許多重要的方法都是相對(duì)于棧頂元素或次棧頂元素來(lái)進(jìn)行的。
如:
addCallMethod(pattern, methodName):調(diào)用棧頂元素的指定方法
addCallMethod(pattern, methodName, paramCount):調(diào)用棧頂元素的指定方法,可指定方法的參數(shù)個(gè)數(shù)
addCallMethod(pattern, methodName, paramCount, paramTypes):調(diào)用棧頂元素的指定方法,可指定方法的參數(shù)個(gè)數(shù),類型
3. XML文件
<?xml version="1.0" encoding="UTF-8" ?>
<Orders>
<Order user="張三" date="2008-11-14" price="12279">
<goods id="1">
<name>IBM筆記本</name>
<price>8999</price>
<count>1</count>
<total_price>8999</total_price>
</goods>
<goods id="2">
<name>雅戈?duì)栁鞣?lt;/name>
<price>1300</price>
<count>2</count>
<total_price>2600</total_price>
</goods>
</Order>
</Orders>4. 通過不同的方式解析這個(gè)xml文件
4.1 通過java編碼方式解析(javabean存儲(chǔ))
根據(jù)這個(gè)xml文件的各個(gè)節(jié)點(diǎn)得出,我們可以創(chuàng)建兩個(gè)javabean來(lái)存儲(chǔ)解析信息。分別為Order.java和good.java。
// 訂單類
package cn.com.bean;
import java.util.ArrayList;
/**
* Order.java:訂單類
* @author ypykip
*
*/
public class Order {
private String user; //對(duì)應(yīng)<Order>標(biāo)簽中的user屬性
private String date; //對(duì)應(yīng)<Order>標(biāo)簽中的date屬性
private String price; //對(duì)應(yīng)<Order>標(biāo)簽中的price屬性
//對(duì)應(yīng)<Order>標(biāo)簽下的所有<good>標(biāo)簽
private ArrayList<Goods> goodsList = new ArrayList<Goods>();
//省略getter和setter...
// 添加商品到訂單
public void add(Goods goods){
this.getGoodsList().add(goods);
}
// 重寫toString()方法,方便于觀察結(jié)果
@Override
public String toString() {
return "Order [user=" + user + ", date=" + date + ", price=" + price
+ ", goodsList=" + goodsList.toString() + "]";
}
}
// 商品類
package cn.com.bean;
package cn.com.bean;
/**
* Goods.java:商品類
* @author ypykip
*
*/
public class Goods {
private String id;
private String name;
private String price;
private String count;
private String total_price;
//省略getter和setter...
@Override
public String toString() {
return "Goods [id=" + id + ", name=" + name + ", price=" + price
+ ", count=" + count + ", total_price=" + total_price +"]";
}
}
// 解析類
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import org.apache.commons.digester.Digester;
import org.xml.sax.SAXException;
import cn.com.bean.Goods;
import cn.com.bean.Order;
/**
* title:通過digester的方式來(lái)解析Order.xml
* @author grk
* 重點(diǎn):理解棧的概念
* 當(dāng)使用addObjectCreate()方法時(shí),創(chuàng)建一個(gè)對(duì)象進(jìn)棧
* 以下的所有操作(有一種情況除外,表明調(diào)用的方法)都是對(duì)棧頂元素來(lái)講的,除非調(diào)用
* addSetNext()方法,移除棧頂元素并執(zhí)行次棧頂元素的指定方法
*
* addCallMethod(pattern, methodName):調(diào)用棧頂元素的指定方法
* addCallMethod(pattern, methodName, paramCount):調(diào)用棧頂元素的指定方法,可指定方法的
* 參數(shù)個(gè)數(shù)addCallMethod(pattern, methodName, paramCount, paramTypes):調(diào)用棧頂元素的
* 指定方法,可指定方法的參數(shù)個(gè)數(shù),類型
*
* addCallParam(pattern, paramIndex):默認(rèn)設(shè)置指定paramIndex參數(shù)為標(biāo)簽內(nèi)容
* addCallParam(pattern, paramIndex, fromStack):設(shè)置指定paramIndex參數(shù)為棧頂元素
* addCallParam(pattern, paramIndex, stackIndex):設(shè)置指定paramIndex參數(shù)為?
* addCallParam(pattern, paramIndex, attributeName):設(shè)置指定paramIndex參數(shù)為標(biāo)簽屬性
* attributeName的值 addObjectParam(pattern, paramIndex, paramObj):設(shè)置指定paramIndex
* 參數(shù)為paramObj
*
* addSetNext(pattern, methodName):調(diào)用次棧頂元素的methodName方法,一般為有一個(gè)參數(shù)的方法,
* 將棧頂元素作為入?yún)?,如list的add方法
*
*/
public class ParseOrder {
public static void main(String[] args) {
parseByJavaBean();
}
/**
* 使用javaBean進(jìn)行存儲(chǔ)
*/
public static void parseByJavaBean(){
// 1.初始化Digester實(shí)例對(duì)象
Digester digester = new Digester();
// 2.解析<Order>標(biāo)簽節(jié)點(diǎn)
//list進(jìn)棧,棧頂元素的list對(duì)象
digester.addObjectCreate("Orders", ArrayList.class);
//Order實(shí)例進(jìn)棧,棧頂元素時(shí)Order實(shí)例對(duì)象
digester.addObjectCreate("Orders/Order", Order.class);
//設(shè)置<Order>標(biāo)簽的屬性
digester.addSetProperties("Orders/Order");
// 3.解析<goods>標(biāo)簽節(jié)點(diǎn)
//Goods實(shí)例對(duì)象進(jìn)棧
digester.addObjectCreate("Orders/Order/goods", Goods.class);
digester.addSetProperties("Orders/Order/goods");
//設(shè)置<goods>下的其他標(biāo)簽內(nèi)容
digester.addBeanPropertySetter("Orders/Order/goods/name");
digester.addBeanPropertySetter("Orders/Order/goods/price");
digester.addBeanPropertySetter("Orders/Order/goods/count");
digester.addBeanPropertySetter("Orders/Order/goods/total_price");
//Goods對(duì)象實(shí)例出棧
digester.addSetNext("Orders/Order/goods", "add");
//Order對(duì)象實(shí)例出棧
digester.addSetNext("Orders/Order", "add");
// 4.加載配置文件
String filePath = "";
filePath = System.getProperty("user.dir")+"/bin/config/Order.xml";
File file = new File(filePath);
// 5.解析
try {
ArrayList list = (ArrayList) digester.parse(file);
System.out.println(list.toString());
} catch (IOException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
}
}
}
運(yùn)行結(jié)果
[Order [user=張三, date=2008-11-14, price=12279, goodsList=[Goods [id=1, name=IBM筆記本, price=8999, count=1, total_price=8999], Goods [id=2, name=雅戈?duì)栁鞣? price=1300, count=2, total_price=2600]]]]
4.2 通過java編碼方式解析(list和map存儲(chǔ))
/**
* 使用list和map進(jìn)行存儲(chǔ)(過程復(fù)雜,不建議使用)
*/
public static void parseByMap(){
Digester digester = new Digester();
// 1.定義Orders節(jié)點(diǎn)規(guī)則,創(chuàng)建一個(gè)List集合
digester.addObjectCreate("Orders", ArrayList.class);
// 2.定義Orders/Order節(jié)點(diǎn)規(guī)則,創(chuàng)建一個(gè)Map集合用來(lái)存儲(chǔ)屬性和內(nèi)容,并將此Map放在上一節(jié)點(diǎn)中的List
digester.addObjectCreate("Orders/Order", HashMap.class);
digester.addSetNext("Orders/Order", "add");
// 3.定義Orders/Order節(jié)點(diǎn)的屬性
digester.addCallMethod("Orders/Order", "put", 2);//調(diào)用棧頂元素map的put方法
digester.addObjectParam("Orders/Order", 0, "name");//設(shè)置key
digester.addCallParam("Orders/Order", 1, "name");//設(shè)置value
digester.addCallMethod("Orders/Order", "put", 2);
digester.addObjectParam("Orders/Order", 0, "date");
digester.addCallParam("Orders/Order", 1, "date");
digester.addCallMethod("Orders/Order", "put", 2);
digester.addObjectParam("Orders/Order", 0, "price");
digester.addCallParam("Orders/Order", 1, "price");
// 4.定義一個(gè)List集合,用來(lái)存儲(chǔ)Orders/Order節(jié)點(diǎn)下的標(biāo)簽
digester.addCallMethod("Orders/Order", "put", 2);
digester.addObjectCreate("Orders/Order", ArrayList.class);
digester.addObjectParam("Orders/Order", 0, "goodsList");
digester.addCallParam("Orders/Order", 1, true);
// 5.定義Orders/Order/goods節(jié)點(diǎn)規(guī)則,分別存儲(chǔ)id,name,price,count,total_price屬性或標(biāo)簽
digester.addObjectCreate("Orders/Order/goods", HashMap.class);
digester.addSetNext("Orders/Order/goods", "add");
digester.addCallMethod("Orders/Order/goods", "put", 2);
digester.addObjectParam("Orders/Order/goods", 0, "id");
digester.addCallParam("Orders/Order/goods", 1, "id");
digester.addCallMethod("Orders/Order/goods/name", "put", 2);
digester.addObjectParam("Orders/Order/goods/name", 0, "name");
digester.addCallParam("Orders/Order/goods/name", 1);
digester.addCallMethod("Orders/Order/goods/price", "put", 2);
digester.addObjectParam("Orders/Order/goods/price", 0, "price");
digester.addCallParam("Orders/Order/goods/price", 1);
digester.addCallMethod("Orders/Order/goods/count", "put", 2);
digester.addObjectParam("Orders/Order/goods/count", 0, "count");
digester.addCallParam("Orders/Order/goods/count", 1);
digester.addCallMethod("Orders/Order/goods/total_price", "put", 2);
digester.addObjectParam("Orders/Order/goods/total_price", 0, "total_price");
digester.addCallParam("Orders/Order/goods/total_price", 1);
String filePath = System.getProperty("user.dir")+"/bin/config/Order.xml";
System.out.println(filePath);
File file = new File(filePath);
System.out.println(file.getAbsolutePath());
try {
ArrayList list = (ArrayList) digester.parse(file);
System.out.println(list.toString());
} catch (IOException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
}
}
4.3 通過xml配置方式解析
4.3.1 OrderConfigRule.xml 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<digester-rules>
<pattern value="Orders">
<object-create-rule classname="java.util.ArrayList" />
<!-- 配置<Order>標(biāo)簽 -->
<pattern value="Order">
<object-create-rule classname="cn.com.bean.Order" />
<set-properties-rule/>
<!-- 配置<goods>標(biāo)簽 -->
<pattern value="goods">
<object-create-rule classname="cn.com.bean.Goods" />
<set-properties-rule>
<alias attr-name="id" prop-name="id" /><!-- id屬性對(duì)應(yīng)javabean的id -->
</set-properties-rule>
<bean-property-setter-rule pattern="name" propertyname="name" /><!-- name屬性對(duì)應(yīng)javabean的name -->
<bean-property-setter-rule pattern="price" propertyname="price" /><!-- price標(biāo)簽對(duì)應(yīng)javabean的price -->
<bean-property-setter-rule pattern="count" propertyname="count" /><!-- count標(biāo)簽對(duì)應(yīng)javabean的count -->
<bean-property-setter-rule pattern="total_price" propertyname="total_price" /><!-- total_price標(biāo)簽對(duì)應(yīng)javabean的total_price -->
<set-next-rule methodname="add" paramtype="cn.com.bean.Goods"/>
</pattern>
<set-next-rule methodname="add" paramtype="cn.com.bean.Order"/>
</pattern>
</pattern>
</digester-rules>
4.3.2 Java解析
public static void parseByXmlConfig() throws IOException, SAXException, URISyntaxException{
// 1.加載規(guī)則配置文件
URL rule = Thread.currentThread()
.getContextClassLoader()
.getResource("config/OrderConfigRules.xml");
// 2.加載待解析的配置文件Order.xml
Reader reader = null;
try {
reader = new InputStreamReader(
new FileInputStream(
new File(System.getProperty("user.dir") + "/bin/config/Order.xml")), "utf-8");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
// 3.根據(jù)規(guī)則配置文件創(chuàng)建Digester實(shí)例對(duì)象
InputSource in = new InputSource(new InputStreamReader(new FileInputStream(new File(rule.toURI()))));
Digester digester = DigesterLoader.createDigester(in);
// 4.進(jìn)行解析并打印結(jié)果
List list = (List) digester.parse(reader);
System.out.println(list.toString());
try {
if(reader != null){
reader.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
結(jié)果
[Order [user=張三, date=2008-11-14, price=12279, goodsList=[Goods [id=1, name=IBM筆記本, price=8999, count=1, total_price=8999], Goods [id=2, name=雅戈?duì)栁鞣? price=1300, count=2, total_price=2600]]]]
5.總結(jié)
如果需要調(diào)用addSetNext()方法時(shí),addObjectCreate()方法和addSetNext()方法最好成對(duì)出現(xiàn)
首先要知道addSetNext()方法是調(diào)用次棧頂元素的方法,一般以棧頂元素為參數(shù)。如上例中使用list和map的方式進(jìn)行存儲(chǔ)時(shí),創(chuàng)建順序分別是Orders—>Order—>goods,對(duì)應(yīng)的list和map分別是list(Orders)—>map(Order)—>list(goodsList)—>map(goods)。當(dāng)遇到Orders/Order節(jié)點(diǎn)時(shí),分別創(chuàng)建了一個(gè)map和一個(gè)list,分別表示訂單和商品集合。當(dāng)遇到 < /order> 結(jié)束標(biāo)簽時(shí)需要調(diào)用list(Orders)的add()方法,即需要此時(shí)的棧頂元素是map(Order)和次棧頂元素是list(Orders)。如果addSetNext()寫在了list(goodsList)創(chuàng)建之后,此時(shí)的棧頂元素和次棧頂元素分別是list(goodsList),map(Order),而map是沒有add方法的,所以會(huì)報(bào)錯(cuò):
java.lang.NoSuchMethodException: No such accessible method: add() on object: java.util.HashMap
通過使用java編碼和配置規(guī)則兩種方式都可以實(shí)現(xiàn)解析,其實(shí)兩者看上去十分相似熟練了其中一種,另一種也就無(wú)師自通
以上就是使用Digester解析XML文件的三種方式小結(jié)的詳細(xì)內(nèi)容,更多關(guān)于Digester解析XML文件的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Springboot+MDC+traceId日志中打印唯一traceId
本文主要介紹了Springboot+MDC+traceId日志中打印唯一traceId,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10
Springboot2.0配置JPA多數(shù)據(jù)源連接兩個(gè)mysql數(shù)據(jù)庫(kù)方式
這篇文章主要介紹了Springboot2.0配置JPA多數(shù)據(jù)源連接兩個(gè)mysql數(shù)據(jù)庫(kù)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09
IntelliJ Idea 2020.1 正式發(fā)布,官方支持中文(必看)
這篇文章主要介紹了IntelliJ Idea 2020.1 正式發(fā)布,官方支持中文了,本文通過截圖的形式給大家展示,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04
Spring Data Jpa+SpringMVC+Jquery.pagination.js實(shí)現(xiàn)分頁(yè)示例
本文介紹了Spring Data Jpa+SpringMVC+Jquery.pagination.js實(shí)現(xiàn)分頁(yè)示例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12
Java設(shè)計(jì)模式中的裝飾器模式簡(jiǎn)析
這篇文章主要介紹了Java設(shè)計(jì)模式中的裝飾器模式簡(jiǎn)析,裝飾模式能夠?qū)崿F(xiàn)動(dòng)態(tài)的為對(duì)象添加功能,是從一個(gè)對(duì)象外部來(lái)給對(duì)象添加功能,通常給對(duì)象添加功能,要么直接修改對(duì)象添加相應(yīng)的功能,要么派生對(duì)應(yīng)的子類來(lái)擴(kuò)展,抑或是使用對(duì)象組合的方式,需要的朋友可以參考下2023-12-12

