使用JXPath訪問java對象、集合和XML文件
作者簡介
肖菁,軟件工程師,IBM developerWorks/Bea dev2dev/sun 技術開發者供稿人,主要研究J2EE、web services以及他們在websphere、weblogic平臺上的實現,擁有IBM的 Developing With Websphere Studio證書。您可以通過guilaida@163.com和作者取得聯系,或者查看作者的主頁獲取更多信息。
摘要
JXPath是Apache組織提供的一個XPath實現,通過JXPath,你可以使用XPath的語法、函數訪問不同的數據內容,包括java對象、集合、xml內容、web應用環境下的各種對象等,本文中作者簡單的介紹了JXPath,并且演示了如何通過JXPath提供的類庫訪問java對象、集合和XML文件的詳細過程,同時給出了簡單的注釋。
一、JXPath簡介
JXPath是apache公司提供的XPath的java實現,屬于jakarta的一部分,最新的版本是1.1,JXPath的主要功能在于一組java類庫來使用XPath的方式訪問符合JavaBeans規范的java類、java集合(Collections)、其他具有動態屬性的對象(如Map、ServletContext等),同時提供了一套擴展機制使我們可以增加對這些對象之外的其他對象模型的支持。
[注]- 1、關于XPath的更多內容請大家訪問XPath的主頁
http://www.w3schools.com/xpath/default.asp - 2、關于JXPath的更多內容請大家訪問JXPath的主頁
http://jakarta.apache.org/commons/jxpath/index.html
二、環境準備
- 1、下載JXPath
JXPath最新版本的二進制代碼下載地址為
http://apache.linuxforum.net/dist/jakarta/commons/jxpath/binaries/commons-jxpath-1.1.zip
- 2、下載eclipse
作者使用了eclipse作為開發工具,請大家到www.eclipse.org下載eclipse的最新版本。
- 3、下載Tomcat
作者使用了Tomcat作為Web容器來演示如何使用JXPath訪問ServletContext中的對象,請大家到jakarta.apache.org下載Tomcat的最新版本。
下面的幾個章節將詳細的演示如何使用JXPath來訪問各種各樣的對象,同時將演示如何通過JXPath來創建對象、修改對象的屬性等功能。
三、使用JXPath訪問對象內容
3.1 訪問JavaBean的屬性
- 1、準備一個符合要求的Java類
作者制作了一個Company類,它包括3個屬性:ID、Name和Address,代碼如下:package org.vivianj.jxpath.examples.pub; import java.util.Comparator; import org.apache.log4j.Logger; public class Company implements Comparator{ public static Logger logger = Logger.getLogger(Company.class); private String name = ""; private int id = 0; private String address = ""; public void setName(String p_name){ this.name = p_name; } public void setId(int p_id){ this.id = p_id; } public void setAddress(String p_address){ this.address = p_address; } public String getName(){ return this.name; } public int getId(){ return this.id; } public String getAddress(){ return this.address; } public int compare(Object o1, Object o2){ return 0; } public boolean equals(Object obj) { boolean result = false; if (obj instanceof Company){ Company company = (Company) obj; if (company.getId()==this.id && company.getName().equals(this.getName()) && company.getAddress().equals(this.getAddress())) result = true; } return result; } }
- 2、使用JXPath來訪問該java類的屬性
現在我們使用JXPath來訪問這個類的屬性,測試代碼如下://實例化一個Company對象 Company company = new Company(); //設置該對象的各個屬性 company.setId(1); company.setName("vivianj組織"); company.setAddress("www.vivianj.org"); //初始化JXPath的上下文環境 JXPathContext context = JXPathContext.newContext(company); //使用XPath語法來訪問該對象的屬性 //getValue方法的參數"name"、"id"、"address"使用了XPath的語法, //他們分別代表要訪問company對象的屬性name、id、address String name = (String)context.getValue("name"); Integer id = (Integer) context.getValue("id"); String address = (String)context.getValue("address");
3.1.1 Lenient 訪問模式
在上面的訪問方式中有可能會出現這樣的情況:如果你要訪問的屬性不是這個Java類的屬性,那么執行過程中系統會報出一個違例-- org.apache.commons.jxpath.JXPathException: No value for xpath: xxx(xxx是你要訪問的屬性的名稱)。
這種情況對于程序的穩定性、健壯性是有害的,這時候我們應該使用JXPath提供的Lenient 訪問模式來避免出現這樣的情況,在Lenient 訪問模式下,如果你訪問了不存在的屬性,系統會返回一個null,而不是拋出一個違例。
要使用Lenient 訪問模式非常簡單,只需要在代碼中增加context.setLenient(true)調用就可以了,具體操作如下:
//實例化一個Company對象 Company company = new Company(); //設置該對象的各個屬性 company.setId(1); company.setName("vivianj組織"); company.setAddress("www.vivianj.org"); //初始化JXPath的上下文環境 JXPathContext context = JXPathContext.newContext(company); //通知系統使用Lenient 訪問模式 context.setLenient(true) //使用XPath語法來訪問該對象的屬性 String name = (String)context.getValue("name1");
[注] name1 不是Company類的屬性,但是由于使用了Lenient 訪問模式,所以系統返回null。
3.2 訪問嵌套屬性
3.1中的例子演示了如何訪問類的簡單類型屬性,如果類的屬性本身就是一個類類型,情況會怎么樣呢,下面的例子將演示這種訪問方式:
- 1、準備Association類
Association類有一個屬性company,他本身是Company類類型package org.vivianj.jxpath.examples.pub; import java.util.ArrayList; import java.util.Collection; public class Association { private Company company; public Company getCompany(){ return this.company; } public void setCompany(Company p_company){ this.company = p_company; } }
- 2、用JXPath訪問嵌套屬性
//實例化Association類 Association association = new Association(); //實例化Company類 Company company = new Company(); company.setId(1); company.setName("vivianj組織"); company.setAddress("www.vivianj.org"); //設置Association對象的company屬性 association.setCompany(company); //初始化JXPath上下文 JXPathContext context = JXPathContext.newContext(association); //使用Lenient訪問模式訪問嵌套屬性 context.setLenient(true); //通過JXPath方法獲得指定屬性的值 //其中getValue方法的參數"company/name"的 //第一部分company代表Association的屬性company, //第二部分("/"符號后面的部分)name代表是company對象的屬性 String name = (String) context.getValue("company/name");
3.3 訪問Java集合
JXPath可以訪問Java集合的內容,這些集合包括java數組、Collection類及其子類,他們的訪問方式基本類似,詳細的情況請參照下面的程序代碼:
- 1、擴展Association類,增加一個提供Company對象的數組的方法
給Association類增加一個方法getCompanysInArray方法,方法的簽名和內容如下:public Company[] getCompanysInArray(){ for (int i = 0 ; i < 5 ; i++){ //實例化新的Company對象 Company comp = new Company(); comp.setId(i); comp.setName("Name" + i ); comp.setAddress("address" + i); //將實例化的對象賦值給到數組的對應元素 companysInArray[i] = comp; } return companysInArray; }
- 2、擴展Association類,增加一個提供Company對象的Collection的方法
給Association類增加一個方法getCompanysInCollection方法,方法的簽名和內容如下:public Collection getCompanysInCollection(){ for (int i = 0 ; i < 5 ; i++){ //實例化新的Company對象 Company comp = new Company(); comp.setId(i); comp.setName("Name" + i ); comp.setAddress("address" + i); //將實例化的對象增加到Collection中 companysInCollection.add(comp); } return companysInCollection; }
3.3.1 訪問方法
通過JXPath訪問數組的詳細代碼如下:
//實例化Association類 Association association = new Association(); //初始化JXPath上下文 JXPathContext context = JXPathContext.newContext(association); //使用Lenient訪問模式訪問嵌套屬性 context.setLenient(true); //通過JXPath語法訪問數組下標為4的記錄的name屬性 //getValue方法的參數"companysInArray[5]/name"中的 //部分companysInArray是Association的屬性, //5代表訪問數組中第5個元素,name表示第五個元素的屬性名 String name = (String) context.getValue("companysInArray[5]/name"); //通過XPath語法訪問集合中第4條記錄的name屬性 //getValue方法的參數" companysInColletion[5]/name"中的 //部分companysInColletion是Association的屬性名, //5代表訪問集合中第5個元素,name表示第五個元素的屬性名 String name = (String) context.getValue("companysInColletion[5]/name");
[注] XPath訪問數組或者集合時,數組或者集合的下標是從1開始,這點和java語言中規定的從0開始有點不同
3.3.2 獲取多條記錄
既然是訪問集合數據,那么經常會出現這樣的需求:需要獲得符合條件的多條記錄。這種情況使用JXPath也非常方便,使用context對象的iterator方法加上相應的XPath信息就可以了,操作后返回的內容保存在Iterator對象中,非常方便就可以訪問。具體的代碼如下:
- 1、按記錄所在的位置獲取
//實例化Association類 Association association = new Association(); //實例化JXPath上下文 JXPathContext context = JXPathContext.newContext(association); //獲得數組中下標大于3的所有記錄 //iterator方法的參數companysInArray [position() > 3]使用了XPath的語法 //其中的companysInArray是Association對象的屬性,他是一個數組 // position()是XPath中的內置函數,獲得記錄在數組中的下標 Itarator companysInArray = context.iterate("companysInArray [position() > 3]"); //獲得集合中所處位置大于3的所有記錄 //iterator方法的參數companysInCollection [position() > 3]使用了XPath的語法 //其中的companysInCollection是Association對象的屬性 //他是一個Collection類型或者是其子類型的一個實例 //position()是XPath中的內置函數,獲得記錄在集合中的位置 Itarator companysInCollection = context.iterate("companysInCollection [position() > 3]");
- 2、按指定的規則獲取
//實例化Association類 Association association = new Association(); //實例化JXPath上下文 JXPathContext context = JXPathContext.newContext(association); //獲得數組中對象的name屬性為'name3'的所有對象 //iterator方法的參數companysInArray [name='name3']使用了XPath的語法 //其中的companysInArray是Association對象的屬性,他是一個數組 //name='name3'是條件表達式,表示返回對象的name屬性值必須是name3 Itarator companysInArray = context.iterate("companysInArray [name='name3']"); //獲得集合中對象的name屬性為'name2'的所有對象 //iterator方法的參數companysInCollection [name='name3']使用了XPath的語法 //其中的companysInCollection是Association對象的屬性 //他是一個Collection類型或者是其子類型的一個實例 //name='name3'是條件表達式,表示返回對象的name屬性值必須是name3 Itarator companysInCollection = context.iterate("companysInCollection [name='name3']");
3.4 訪問Map對象的內容
- 1、準備符合條件的java類
package org.vivianj.jxpath.examples.pub; import java.util.HashMap; import java.util.Map; import org.apache.commons.jxpath.JXPathContext; public class MyMapSource { private Map map = new HashMap(); public MyMapSource(){ map.put("id",new Integer(5)); map.put("name","name"); } public Map getMapSource(){ return this.map; } }
- 2、使用JXPath訪問Map的內容
//實例化MyMapSource對象 MyMapSource myMapSource = new MyMapSource(); //實例化JXPath上下文 JXPathContext context = JXPathContext.newContext(myMapSource); //通過JXPath訪問Map對象的內容 // getValue方法的參數使用了XPath語法 // mapSource/id中的mapSource表示MyMapSource對象的屬性, //他是一個Map類型的對象,id表示獲取該Map對象的id字段 Integer id = (Integer) context.getValue("mapSource/id");
3.5 訪問XML文件
- 1、編寫自己的XML文件
<?xml version="1.0" ?> <companys> <company id="101"> <name>sun</name> <address> <street>18 #,WenShan Road</street> </address> </company> <company id="102"> <name>ibm</name> <address> <street>18 #,WenEr Road</street> </address> </company> </companys>
- 2、編寫一個類,返回符合條件的company內容
package org.vivianj.jxpath.examples.pub; import java.net.URL; import org.apache.commons.jxpath.Container; import org.apache.commons.jxpath.xml.DocumentContainer; public class Companys { private Container companys = null; public Container getCompanys(){ if (companys == null){ //獲取XML文件的內容 URL url = getClass().getResource("companys.xml"); //將XML的內容綁定到companys對象 companys = new DocumentContainer(url); } return companys; } }
- 3、使用JXPath訪問XML文件的內容
//實例化Companys對象 Companys companys = new Companys(); //初始化JXPath上下文 JXPathContext context = JXPathContext.newContext(companys); //獲得指定記錄的子元素的內容 /*getValue方法的參數 "companys/companys/company[@id = '101']/address/street" 使用了XPath語法 其中的第一個companys表示訪問Companys對象的companys屬性 第二個companys表示訪問XML數據中的companys元素 company、address、street都是xml中的元素的名字 @id = '101'是一個條件表達式,表示符合條件的company元素的id屬性必須是101 */ String street = (String)context.getValue( "companys/companys/company[@id = '101']/address/street"); //通過JXPath獲取xml元素的屬性的值 logger.debug("id=" + context.getValue("companys/companys/company[@id = '101']/@id")); //通過JXPath獲取xml元素的子元素的值 logger.debug("p_id=" + context.getValue("companys/companys/company[name = 'sun']/name"));
[注] 通過JXPath訪問xml內容時,如果訪問屬性,必須增加一個@符號,以示區別
四、總結
JXPath是apache組織提供的一個XPath的java實現,目前最新的版本是1.1,通過JXPath提供的豐富的類庫,使用者可以很簡單的使用XPath語法來訪問java對象、集合、xml內容、web應用環境下的各種對象等。
本文中作者一開始簡單的介紹了JXPath的相關信息,接下來的章節中,作者結合實例,詳細的演示了如何通過JXPath提供的豐富的類庫訪問java對象、集合和XML文件的詳細過程,同時給出了簡單的注釋,希望能夠幫助大家進入JXPath的精彩世界。JXPath的強大功能遠不止此,請大家關注作者的后續文章。
工具下載
- 1、JXPath包下載
http://apache.linuxforum.net/dist/jakarta/commons/jxpath/binaries/commons-jxpath-1.1.zip
- 2、Eclipse工具下載
www.eclipse.org
參考資料
posted on 2005-05-24 19:09 weidagang2046 閱讀(2123) 評論(0) 編輯 收藏 所屬分類: Java