使用jxpath 進行java對象查詢

          作者:Bart van Riel
          原文出處:http://www.javaworld.com/javaworld/jw-03-2007/jw-03-jxpath.html?page=1

          摘要:在最近的一個項目里,我需要遍歷一個java對象樹并從對象中獲取值,為了避免使用重復的if else 語句,我需要一個工具使得我的工作可以更輕松,“我需要一個id為X的對象,并且要獲取這個對象的A屬性”,實際上,我需要一個對象查詢工具!

          JXPath 就是這樣一個對象查詢工具,它是一個apache common 組件,利用它,你可以使用著名的xpath 規則語言來查詢復雜的java 對象樹。
          我在我的項目中大量使用了JXPath,它對于開發速度的提升是相當可觀的,同時也使得值抽取算法相當的輕快。

          盡管如此,關于JXPath 的文檔并不多。由于我正在進行深度開發這個組件,所以我決定在我的一個JXPath 全面指南里寫下我的研究成果,你可以在我的網站上找到它,這篇文章是那篇指南的縮寫版,能夠使得你迅速開始JXPath 之旅。

          示例模型

          為了演示的目的,我們采取了一個相對簡單的模型:一個公司有多個部門,一個部門有多個員工,下面是模型圖:

          Class model

          很自然,我們需要一些模型數據:

          公司:

          Acme Inc.

          Sales 銷售部:

          Johnny, Sales rep, 45

          Sarah, Sales rep, 33

          Magda, Office assistant, 27


          Accounting 會計部

          Steve, Head controller, 51

          Peter, Assistant controller, 31

          Susan, Office assistant, 27



          執行簡單的JXPath 查詢

          最簡單的查詢就是從對象樹中查找一個對象,例如,要查找公司,用下面的代碼:

          JXPathContext context = JXPathContext.newContext(company);
          Company c 
          = (Company)context.getValue(".");


          第一行展示了context (上下文)的創建,也就是對象樹中所有JXPath的xpath 規則的起始點(相當于XML文檔的根節點元素)。
          第二行執行了實際的查詢,因為這里的上下文是以公司開始的,所以要獲取公司對象,只需要使用當前元素選擇器“.”。

          使用謂詞和變量

          一個員工是部門的子對象,獲取員工名為johnny 的代碼如下:

          Employee emp = (Employee)context.getValue("/departmentList/employees[name='Johnny']");

          這段代碼可以這樣理解:遍歷所有的部門尋找姓名為johnny的員工

          上面的代碼段解釋了如何使用謂詞進行對象的搜索,使用謂詞相當于SQL語句中的where字句,我們可以綁定多條謂詞:

          Employee emp = 
             (Employee)context.getValue(
          "/departmentList/employees[name='Susan' and age=27]");


          如果你不是只進行一次查詢的話,像上面這樣的硬編碼一般都不可取,更好的方法是定義一個可重用的查詢,那么你就可以在多條語句中進行重用,為適應參數化的查詢JXPath 支持變量查詢,代碼如下:

           context.getVariables().declareVariable("name""Susan");
          context.getVariables().declareVariable(
          "age"new Integer(27));
          Employee emp 
          = 
             (Employee)context.getValue(
          "/departmentList/employees[name=$name and age=$age]");


          對于集合元素的迭代


          JXPath 提供了一個迭代器,可以對查詢的結果進行迭代,下面的代碼:

           for(Iterator iter = context.iterate("/departmentList"); iter.hasNext();){
             Department d 
          = (Department)iter.next();
             
          //
          }


          迭代所有員工的代碼如下:

           for(Iterator iter = context.iterate("/departmentList/employees"); iter.hasNext();){
             Employee emp 
          = (Employee)iter.next();
             
          //
          }


          下面是一個結合變量綁定和迭代的例子:

           context.getVariables().declareVariable("deptName""Sales");
          context.getVariables().declareVariable(
          "minAge"new Integer(30));
          for(Iterator iter = context.iterate("/departmentList
               [name=$deptName]/employees[age>$minAge]"); iter.hasNext();){
             Employee emp = (Employee)iter.next();
             
          //
          }


          指針 Pointers

          指針是JXPath的一個工具類,用來代表對象樹中的一個對象的引用,比如,一個指針可能代表了第二個部門的第一個員工,相比于直接從對象樹中查找對象的對象,指針提供了一些額外的功能,比如在相關上下文下的相關查詢,下面有具體的例子:

          使用指針

          使用指針指向一個對象和從對象樹中獲取一個對象是相等的:

           JXPathContext context = JXPathContext.newContext(company);
          Pointer empPtr 
          = context.getPointer("/departmentList[name='Sales']/employees[age>40]");

          System.out.println(empPtr);
          //output: /departmentList[1]/employees[1]

          System.out.println(((Employee)empPtr.getValue()).getName());
          //output: Johnny

          可以看出,一個指針只是代表了一個對象的位置,而不是對象本身,同時也可以看出,可以通過指針的getValue方法獲取指針代表的對象。

          相關上下文下的相關查詢
          由于指針是代表對象的位置,所以可以被用來作為整個對象樹來導航的一個引用,為了做到這點,我們可以把指針指向根對象(就好像上面例子中的公司對象),也就是所謂的相關上下文,在相關上下文,你可以通過相關查詢進行整個對象樹的查詢,指針的這個高級使用提供了極大的彈性,下面我們例子說明:

          開始,我們來創建一個相關上下文:

           for(Iterator iter = context.iteratePointers("/departmentList[name='Sales']
               /employees[age>30]"); iter.hasNext();){
             Pointer empPtr = (Pointer)iter.next();
             JXPathContext relativeContext 
          = context.getRelativeContext(empPtr);
          }


           使用相關上下文,XPath 查詢能夠在對象樹的子節點,父節點,超父節點等進行執行,具體看下面的例子:

           //Current employee
          Employee emp = (Employee)relativeContext.getValue(".");

          //Employee name
          String name = (String)relativeContext.getValue("./name");

          //Name of the Department this Employee belongs to (a parent object)
          String deptName = (String)relativeContext.getValue("../name");

          //Name of the Company this Employee belongs to (a 'grandparent' object)
          String compName = (String)relativeContext.getValue("../../name");

          //All coworkers of this Employee (sibling objects)
          for(Iterator empIter = relativeContext.iterate("../employees"); empIter.hasNext();){
             Employee colleague 
          = (Employee)empIter.next();
             
          //
          }



          總結

          JXPath 在遍歷,導航,和查詢復雜的對象樹時是非常有用的工具,由于它使用 xpath 語言 進行查詢,因此有大量的資料可以幫助構建高效的復雜對象樹查詢,指針和相關上下文的加入使得查詢更加方便。


          相關資源
          1,下載本文的源代碼 http://www.javaworld.com/javaworld/jw-03-2007/jxpath/jw-03-jxpath.zip
          2,查看全面指南 http://www.tutorials.tfo-eservices.eu/
          3,XPATH 指南 http://www.w3schools.com/xpath

          不要忘了,廣告也精彩哦

          posted on 2007-05-15 11:13 快譯站 閱讀(1185) 評論(0)  編輯  收藏 所屬分類: 技術前沿

          導航

          留言簿(3)

          隨筆分類

          隨筆檔案

          友情鏈接

          最新評論

          主站蜘蛛池模板: 当涂县| 夏邑县| 庆云县| 盱眙县| 宜君县| 黔西县| 淮阳县| 宝兴县| 九龙县| 华安县| 社旗县| 蒙城县| 嘉兴市| 沙河市| 江孜县| 临泉县| 富阳市| 灵台县| 乳山市| 库车县| 辉南县| 来凤县| 荣昌县| 右玉县| 泌阳县| 垫江县| 普定县| 临夏县| 门头沟区| 河北省| 平遥县| 屏东市| 五原县| 普兰店市| 当涂县| 呼图壁县| 洛扎县| 溆浦县| 胶南市| 房产| 丁青县|