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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在使用dom4j获取节点的完整路径和对应的行号时,你可以使用XPath表达式和节点的Location Path。 首先,使用XPath表达式来获取节点的完整路径。XPath表达式是一种用于在XML文档中定位节点的语言。在dom4j中,你可以使用`XPath`类来执行XPath表达式。假设你要获取名为`node`的节点的完整路径,可以按照以下步骤进行: 1. 创建一个`Document`对象,表示你的XML文档。假设你的XML文档已经被解析为`Document`对象,并且存储在变量`document`中。 2. 创建一个`XPath`对象,并使用XPath表达式来指定要获取的节点。例如,对于名为`node`的节点,可以使用XPath表达式`//node`。 ```java XPath xpath = DocumentHelper.createXPath("//node"); ``` 3. 使用`evaluate()`方法执行XPath表达式,并传入`document`作为参数。这将返回一个节点列表。 ```java List<Node> nodeList = xpath.evaluate(document); ``` 4. 遍历节点列表,并使用`getPath()`方法获取每个节点的完整路径。 ```java for (Node node : nodeList) { String path = node.getPath(); System.out.println("Node path: " + path); } ``` 接下来,获取对应节点的行号。dom4j提供了一个`Dom4jXPath`类,可以在执行XPath表达式时获取节点的行号。你可以按照以下步骤进行: 1. 导入`Dom4jXPath`类。 ```java import org.dom4j.io.Dom4jXPath; ``` 2. 创建一个`Dom4jXPath`对象,并使用XPath表达式来指定要获取的节点。例如,对于名为`node`的节点,可以使用XPath表达式`//node`。 ```java Dom4jXPath xpath = new Dom4jXPath("//node"); ``` 3. 使用`setDocument()`方法将`document`对象设置为`Dom4jXPath`对象的文档。 ```java xpath.setDocument(document); ``` 4. 使用`selectNodes()`方法执行XPath表达式,并传入`document`作为参数。这将返回一个节点列表。 ```java List<Node> nodeList = xpath.selectNodes(document); ``` 5. 遍历节点列表,并使用`getLineNumber()`方法获取每个节点的行号。 ```java for (Node node : nodeList) { int lineNumber = node.getLineNumber(); System.out.println("Node line number: " + lineNumber); } ``` 通过以上步骤,你可以使用dom4j获取节点的完整路径和对应的行号。记得替换掉代码中的`//node`为你实际需要获取的节点的XPath表达式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值