JXpath學習筆記

最近學習了下Apache Commons項目下的一個子項目JXpath的使用,結合官方文檔與網絡上的一些入門教程小試用了一把。下面把學習內容整理了下,以便日後查看。

1      簡介

JXPath定義了一個簡單的XPath解釋器,可用於定位各種對象——JavaBeans, Maps, Servlet contexts, DOM——以及它們的混合。

JXPath的核心類是JXPathContext,所以應用幾乎總是會用到該類。

2      應用及示例

下面我們用一個示例來說明其應用,示例使用 Company --> Department --> Employee的結構來展示JXPath的應用。

Company

Department

Employee

String name;

List<Department> departments;

String name;

Set<Employee> employees;

String name;

int age;

Map<String, String> contacts

Company[“MS”]:

  Department[“Development”]

  Department[“Administrative”]

Department[Development]:

  Employee[“Eric”]

Employee[“Andy”]

Department[Administrative]:

  Employee[“Lily”]

  Employee[“Lucy”]

Employee[“Eric”]:

  age: 20

  contacts:

<home, “1234567”>

<office, “7654321”>

Employee[“Andy”]:

  age: 28

Employee[“Lily”]

  age: 22

Employee[“Lucy”]

  age: 25

我們共用一個JXPathContext,如下:

JXPathContext context = JXPathContext.newContext( company );

2.1      選取當前節點

Company c = (Company) context.getValue( "." );

由於我們使用的company創建的JXPathContext,所以,company是根節點,也是當前節點。使用“.”選擇器就可以選取當前節點,即company。表達式 c == company 也會返回true

2.2      訪問屬性

String companyName = (String) context.getValue( "name" );

當前節點companyname屬性,所以可得company name—— MS

2.3      謂語

Employee lily = (Employee) context.getValue( "/departments/employees[name='Lily']" );

謂語類似於SQL中的WHERE語句,有篩選作用,謂語被嵌在方括號中。以上代碼可以選出所有部門所有員工中叫“Lily”的員工。

謂語中可以使用運算符。

context.getValue( "/departments/employees[name='Lily1' or age=22]" );

context.getValue( "/departments/employees[name='Lily' and age=22]" );

 

2.4      變量

context.getVariables().declareVariable( "name", "Eric" );

Employee eric = (Employee) context.getValue( "/departments/employees[name=$name]" );

查詢中是可以使用變量的,只需要取得context關聯的變量池,聲明變量即可。

引用變量時,只需要在變量名前加前導符“$”即可。

聲明的變量不必是字符串,可以是任意對象。

2.5      寬鬆模式

context.setLenient( true );

Employee clark = (Employee) context.getValue( "/departments/employees[name='clark']" );

如果指定的xpath不能映射到任何已存在的節點,那麼將拋出異常。但是,這個限制在調用context.setLenient( true );後將被放寬,僅返回null,而不拋出異常。

2.6      訪問Map

context.getValue( "/departments/employees[name='Eric']/contacts/home" );

context.getValue( "/departments/employees[name='Eric']/contacts[@name='office']" );

我們知道Employee類中有contacts屬性,爲Map類型。名爲Eric的員工存儲了兩種聯繫方式:homeoffice。上面的代碼分別用兩種語法選取了兩種聯繫方式。

JXPath只支持key爲字符串的Map

2.7      訪問集合

2.7.1       迭代單個集合

                   for ( Iterator<?> iter = context.iterate( "/departments" ); iter.hasNext();  )

                   {

                            Department dept = (Department) iter.next();

                            System.out.println(dept.getName());

                   }

上面的代碼會得到company下的departments的迭代器,即可遍歷所有部門。

2.7.2       迭代多個集合

                   for ( Iterator<?> iter = context.iterate( "/departments/employees" ); iter.hasNext(); )

                   {

                            Employee emp = (Employee) iter.next();

                            System.out.println(emp.getName());

                   }

與迭代單個集合不同,上面的代碼選取的節點不只是一個集合,它選取了所有部門下的所有員工集合。但是返回的迭代器可以一次性迭代遍歷所有員工,儘管他們在不同部門的員工集合中。

2.7.3       下標

Employee emp2 = (Employee) context.getValue( "/departments/employees[2]" );

對於數組或集合形式的節點,我們可以使用下標的方式進行訪問。

Set這種無序的集合而言,它的元素順序是其迭代順序,由於迭代順序是不可預測的,所以通常不會使用下標訪問Set

注:下標是從1開始,而不是0

下標訪問時,根據迭代多個集合的思維來預測結果會有一些偏差。

對上面代碼而言,並沒有把所有部門的員工合併,然後選取第2個員工。相反,程序將進行路徑嘗試。首先,嘗試 /departments[1]/employees[2]能否選取節點,如果可以返回該節點;如果不能則嘗試 /departments[2]/employees[2]能否選取節點……以此類推。所以,上面代碼返回的結果應是查找到的第1個至少有2個員工的部門的第2個員工。

以上說明的是getValue()的行爲,但是對於iterate()又有點不同。

              for ( Iterator<?> iter = context.iterate( "/departments/employees[2]" ); iter.hasNext(); )

              {

                     Employee emp = (Employee) iter.next();

                     System.out.println(emp.getName());

              }

相同的是,iterate()也會進行路徑嘗試,但不同在於它會返回所有嘗試通過的節點的集合的迭代器。對上面的代碼而言,返回的迭代器對應的集合應該是所有至少擁有2個員工的部門下的第2個員工的集合。本例中,Development部門有AndyEricAdministrative部門有LucyLily——員工按順序列出的——那麼迭代出的員工應是EricLily

 

【參考】

http://www.javaworld.com/article/2077700/data-storage/java-object-queries-using-jxpath.html

發佈了52 篇原創文章 · 獲贊 7 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章