Java对象查询方法:Jxpath(转译)

时间:2022-12-08 12:57:50


在JAVA对象中,如何进行有效的查询呢,这一直是个很值得探讨的问题.大家知道,在XML中,要找元素如何找呢?没错,通过XPATH
是个不错的办法,同样道理,新近发现原来在JAVA中,也居然有象XPATH里的东西,这就是著名的apache commons库中包含的jxpath包中所提供的功能,这可以在 ​​​http://jakarta.apache.org/commons/jxpath/​​​中找到相关下载.下面来简单介绍一下(注:本文内容主要来自

​​​http://today.java.net/pub/a/today/2006/08/03/java-object-querying-using-jxpath.html​​​
,本人有所改动和润色)
     
什么是JXPATH
     首先,JXPATH是通过简单的表达式,可以在JAVA的类对象层次中进行查询.我们还是来看简单的例子来说明问题:
      比如,我们的例子中,有一些公司,每间公司有不同的部门,每个不同的雇员,而且当然,公司有它们的CEO.雇员还有比如姓名,电话等属性.

      假设我们要查找在California的公司中,有哪些公司的部门中有超过10位员工的话,以前会这样写的

for (Iterator companies =  database.getCompanies().iterator();  companies.hasNext();)

{

//获得所有公司

Company company = (Company)companies.next();


//获得在California的公司

if (company.getLocation().equals("CAA")) {


for (Iterator departments =company.getDepartments().iterator();departments.hasNext(); )

{


//获得公司的所有部门

Department department =

(Department)departments.next();


if (department.getEmployees().size() > 10) {

System.out.println(department);

}

}

}

}




  而如果用JXPATH的话,可以这样写

Iterator departments = context.iterate(

"/companies[location='CA']" +

"/departments[count(employees) > 10]");

while (departments.hasNext()) {

System.out.println(departments.next());

}



可以看到,用了JXPATH的话,只需要简单指定好表达式,马上就可以了.下面来简单介绍下一些写法
比如:

要多的所有的公司:/companies
获得公司下的部门:/companies/departments
获得在某个地方的公司:/companies[location='CA'],这里,location为companies的属性

要获得位于CA的公司中含有开发部门的公司的话,可以这样:
/companies[location='CA']/departments[contains(name, 'Development')]

要获得某个部门雇员数大于10人的:/companies/departments[count(employees) > 10]


要获得SUN公司下第二个部门:/companies[name='Sun Microsystems']/departments[2]
要注意的是,JXPATH的序号是从1开始,不是从0开始

和XPATH类似,可以象这样
/companies[name='Sun Microsystems']/
           departments[last()]

接下来说下如何配合JAVA代码来实现查询
首先,对比如对于company,employee,department这三个类,都必须设置getter,setter方法,
  然后,比如要有
public List getCompanies();

后,则可以使用
/Companies来查询了

而每个公司下面要查询所有的部门的话,先设置
public List getDepartments();
方法,
然后再用/companies/departments可以查询了;

提供public String getName();方法,则在下面的场景中会被调用:

/companies/departments[name='Server Development']

又比如,假设已经设置了一个MAP,里面存放某人的电话,比如有工作电话,私人电话:

Map numbers = employee.getTelephoneNumbers();
String workNumber =
          (String)numbers.get("work number");

上面是取得某个雇员的工作电话,但必须这样写JXPATH
.../employees[1]/
          telephoneNumbers[@name='work number']
@name是用来指定MAP中的KEY的,而不能简单将上面的写成
.../employees[1]/
          telephoneNumbers/work number

最后,我们可以结合起来使用jxpath了,首先先声明根对象,也就是说,你要先构造出一个类层次出来,比如已经构造出一个类层次,叫
database类,则:
JXPathContext context = JXPathContext.
                            newContext(database);
其中database类里面已经有所有的公司的实例了,这里先取出其上下文context;然后,
Iterator departments = context.iterate("/companies[location='WA']" +
        "/departments[count(employees) > 10]");

则取出所有在WA的那些部门人数>10的所有公司的集合了

最后输出:
while (departments.hasNext()) {
  Department dept = (Department)i.next();
}

看,多简单呀.

最后,强烈大家去下载本文的例子去看看,在ECLIPSE里跑一下就可以了,写的很清晰
代码: ​​​http://today.java.net/today/2006/08/03/source_code.tar.gz​​​