原文出处Q?a >http://www.javaworld.com/javaworld/jw-03-2007/jw-03-jxpath.html?page=1
摘要Q在最q的一个项目里Q我需要遍历一个java对象树ƈ从对象中获取|Z避免使用重复的if else 语句Q我需要一个工具得我的工作可以更LQ?#8220;我需要一个id为X的对象,q且要获取这个对象的A属?#8221;Q实际上Q我需要一个对象查询工P
JXPath 是q样一个对象查询工P它是一个apache common lgQ利用它Q你可以使用著名?a target=_blank>xpath 规则语言来查询复杂的java 对象树?br>我在我的目中大量用了JXPathQ它对于开发速度的提升是相当可观的,同时也得值抽取算法相当的d?br>
管如此Q关于JXPath 的文档ƈ不多。由于我正在q行深度开发这个组Ӟ所以我军_在我的一个JXPath 全面指南里写下我的研I成果,你可以在我的|站上找到它Q这文章是那篇指南的羃写版Q能够得你q速开始JXPath 之旅?br>
CZ模型
Z演示的目的,我们采取了一个相对简单的模型Q一个公司有多个部门Q一个部门有多个员工Q下面是模型图:

很自Ӟ我们需要一些模型数据:
公司Q?
Acme Inc.
Sales 销售部Q?/p>
Johnny, Sales rep, 45
Sarah, Sales rep, 33
Magda, Office assistant, 27
Accounting 会计?/p>
Steve, Head controller, 51
Peter, Assistant controller, 31
Susan, Office assistant, 27
执行单的JXPath 查询
最单的查询是从对象树中查找一个对象,例如Q要查找公司Q用下面的代码:
JXPathContext context = JXPathContext.newContext(company);
Company c = (Company)context.getValue(".");

W一行展CZcontext Q上下文Q的创徏Q也是对象树中所有JXPath的xpath 规则的v始点Q相当于XML文档的根节点元素Q?br>W二行执行了实际的查询,因ؓq里的上下文是以公司开始的Q所以要获取公司对象Q只需要用当前元素选择?#8220;.”?br>
使用谓词和变?br>
一个员工是部门的子对象Q获取员工名为johnny 的代码如下:
Employee emp = (Employee)context.getValue("/departmentList/employees[name='Johnny']");

q段代码可以q样理解Q遍历所有的部门L姓名为johnny的员?br>
上面的代码段解释了如何用谓词进行对象的搜烦Q用谓词相当于SQL语句中的where字句Q我们可以绑定多条谓词:
Employee emp =
(Employee)context.getValue("/departmentList/employees[name='Susan' and age=27]");

如果你不是只q行一ơ查询的话,像上面这L编码一般都不可取,更好的方法是定义一个可重用的查询,那么你就可以在多条语句中q行重用Qؓ适应参数化的查询JXPath 支持变量查询Q代码如下:
context.getVariables().declareVariable("name", "Susan");
context.getVariables().declareVariable("age", new Integer(27));
Employee emp =
(Employee)context.getValue("/departmentList/employees[name=$name and age=$age]");

对于集合元素的P?br>
JXPath 提供了一个P代器Q可以对查询的结果进行P代,下面的代码:

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

q代所有员工的代码如下Q?br>

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

下面是一个结合变量绑定和q代的例子:
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的一个工LQ用来代表对象树中的一个对象的引用Q比如,一个指针可能代表了W二个部门的W一个员工,相比于直接从对象树中查找对象的对象,指针提供了一些额外的功能Q比如在相关上下文下的相x询,下面有具体的例子Q?br>
使用指针
使用指针指向一个对象和从对象树中获取一个对象是相等的:
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

可以看出Q一个指针只是代表了一个对象的位置Q而不是对象本w,同时也可以看出,可以通过指针的getValueҎ获取指针代表的对象?br>
相关上下文下的相x?br>׃指针是代表对象的位置Q所以可以被用来作ؓ整个对象树来D的一个引用,Z做到q点Q我们可以把指针指向根对象(好像上面例子中的公司对象)Q也是所谓的相关上下文,在相关上下文Q你可以通过相关查询q行整个对象树的查询Q指针的q个高使用提供了极大的Ҏ,下面我们例子说明Q?br>
开始,我们来创Z个相关上下文Q?br>
for(Iterator iter = context.iteratePointers("/departmentList[name='Sales']
/employees[age>30]"); iter.hasNext();){
Pointer empPtr = (Pointer)iter.next();
JXPathContext relativeContext = context.getRelativeContext(empPtr);
}

使用相关上下文,XPath 查询能够在对象树的子节点Q父节点Q超父节点等q行执行Q具体看下面的例子:
//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 在遍历,DQ和查询复杂的对象树时是非常有用的工P׃它?xpath 语言 q行查询Q因此有大量的资料可以帮助构建高效的复杂对象树查询,指针和相关上下文的加入得查询更加方ѝ?br>
相关资源Q?br>1Q下载本文的源代?http://www.javaworld.com/javaworld/jw-03-2007/jxpath/jw-03-jxpath.zip
2Q查看全面指?http://www.tutorials.tfo-eservices.eu/
3QXPATH 指南 http://www.w3schools.com/xpath
不要忘了Q广告也_ֽ?/span>

]]>