模块 java.xml

包 javax.xml.xpath


javax.xml.xpath
提供一个 object-model neutral API,用于评估 XPath 表达式和访问评估环境。

XPath API 支持XML 路径语言 (XPath) 1.0 版


1. XPath 概述

XPath 语言为从 XML 文档中选择节点提供了一种简单、简洁的语法。 XPath 还提供了将 XML 文档对象模型 (DOM) 树中的节点转换为boolean、双精度值或字符串值的规则。 XPath 是 W3C 定义的语言,也是 W3C 官方推荐的语言; W3C 主持 XML 路径语言 (XPath) 1.0 版规范。

XPath 始于 1999 年,作为 XSLT 和 XPointer 语言的补充,但最近作为一种独立的语言变得流行,因为单个 XPath 表达式可用于替换多行 DOM API 代码。

2. XPath 表达式

一个 XPath expression 由一个 location path 和一个或多个可选的 predicates 组成。表达式还可以包括 XPath 变量。

下面是一个简单的 XPath 表达式的示例:

   /foo/bar
 

此示例将选择 XML 文档中的 <bar> 元素,如下所示:

   <foo>
     <bar/>
   </foo>
 

表达式 /foo/bar 是位置路径的示例。虽然 XPath 位置路径类似于 Unix 风格的文件系统路径,但一个重要的区别是 XPath 表达式返回与表达式匹配的 all 个节点。因此,以下文档中的所有三个 <bar> 元素都将由 /foo/bar 表达式选择:

   <foo>
     <bar/>
     <bar/>
     <bar/>
   </foo>
 

特殊的位置路径运算符 // 选择 XML 文档中任意深度的节点。以下示例选择所有 <bar> 元素,而不考虑它们在文档中的位置:

   //bar
 

通配符 * 会导致选择所有元素节点。以下示例选择 <foo> 元素的所有子元素:

   /foo/*
 

除了元素节点,XPath 定位路径还可以寻址属性节点、文本节点、注释节点和处理指令节点。下表给出了每种节点类型的位置路径示例:

位置路径示例
定位路径 Description
/foo/bar/@id 选择 <bar> 元素的属性 id
/foo/bar/text() 选择 <bar> 元素的文本节点。转义字符数据和非转义字符数据之间没有区别。
/foo/bar/comment() 选择 <bar> 元素中包含的所有注释节点。
/foo/bar/processing-instruction() 选择 <bar> 元素中包含的所有处理指令节点。

谓词允许细化由 XPath 位置路径选择的节点。谓词的形式为 [expression] 。以下示例选择包含值为 trueinclude 属性的所有 <foo> 元素:

   //foo[@include='true']
 

谓词可以相互附加以进一步细化表达式,例如:

   //foo[@include='true'][@mode='bar']
 

3. XPath 数据类型

当 XPath 表达式选择 XML 文档中的节点时,XPath API 允许将所选节点合并为以下数据类型之一:

  • Boolean
  • Number
  • String

3.1 QName类型

XPath API 定义了以下 QName 类型来表示 XPath 评估的返回类型:

返回类型由用于评估表达式的方法调用中的 QName 参数指定,它是对 XPathExpression.evaluate(...)XPath.evaluate(...) 方法的调用。

当请求 Boolean 返回类型时,如果选择了一个或多个节点,则返回 Boolean.TRUE;否则,返回 Boolean.FALSE

String 返回类型便于从文本节点、属性节点、注释节点或处理指令节点中检索字符数据。在元素节点上使用时,返回子文本节点的值。

Number 返回类型尝试将节点的文本合并为 double 数据类型。

3.2 类类型

除了 QName 类型之外,XPath API 还支持通过 XPathExpression.evaluateExpression(...)XPath.evaluateExpression(...) 方法使用 Class 类型。 XPath 数据类型映射到类类型,如下所示:
  • Boolean -- Boolean.class
  • Number -- Number.class
  • String -- String.class
  • Nodeset -- XPathNodes.class
  • Node -- Node.class

Number 的子类型中,仅支持 Double, IntegerLong

3.3 枚举类型

枚举类型在 XPathEvaluationResult.XPathResultType 中定义,提供上述 QName 和类类型之间的映射。使用 XPathExpression.evaluateExpression(...)XPath.evaluateExpression(...) 方法计算表达式的结果将属于这些类型之一。

请注意 Enum 和 QName 映射之间的差异:

4.XPath上下文

XPath 位置路径可能与文档中的特定节点相关,称为 context 。上下文包括:

  • 一个节点(上下文节点)
  • 一对非零正整数(上下文位置和上下文大小)
  • 一组变量绑定
  • 函数库
  • 表达式范围内的命名空间声明集

它是一个 XML 文档树,表示为节点的层次结构,例如,在 JDK 实现中是一个 Node

5. 使用 XPath API

考虑以下 XML 文档:
 <widgets>
 <widget>
 <manufacturer/>
 <dimensions/>
 </widget>
 </widgets>
 

可以通过以下过程选择 <widget> 元素:

   // parse the XML as a W3C Document
   DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
   Document document = builder.parse(new File("/widgets.xml"));

   //Get an XPath object and evaluate the expression
   XPath xpath = XPathFactory.newInstance().newXPath();
   String expression = "/widgets/widget";
   Node widgetNode = (Node) xpath.evaluate(expression, document, XPathConstants.NODE);

   //or using the evaluateExpression method
   Node widgetNode = xpath.evaluateExpression(expression, document, Node.class);
 

通过引用 <widget> 元素,可以编写相对 XPath 表达式来选择 <manufacturer> 子元素:

   XPath xpath = XPathFactory.newInstance().newXPath();
   String expression = "manufacturer";
   Node manufacturerNode = (Node) xpath.evaluate(expression, widgetNode, XPathConstants.NODE);

   //or using the evaluateExpression method
   Node manufacturerNode = xpath.evaluateExpression(expression, widgetNode, Node.class);
 

在上面的示例中,XML 文件在传递给 XPath API 之前被读入 DOM 文档。以下代码演示了使用 InputSource 将其留给 XPath 实现来处理它:

   XPath xpath = XPathFactory.newInstance().newXPath();
   String expression = "/widgets/widget";
   InputSource inputSource = new InputSource("widgets.xml");
   NodeList nodes = (NodeList) xpath.evaluate(expression, inputSource, XPathConstants.NODESET);

   //or using the evaluateExpression method
   XPathNodes nodes = xpath.evaluateExpression(expression, inputSource, XPathNodes.class);
 

在上述情况下,预期结果的类型是已知的。如果结果类型未知或任何类型,XPathEvaluationResult 可用于确定返回类型。下面的代码演示了用法:

   XPathEvaluationResult<?> result = xpath.evaluateExpression(expression, document);
   switch (result.type()) {
     case NODESET:
       XPathNodes nodes = (XPathNodes)result.value();
       ...
       break;
   }
 

XPath 1.0 Number 数据类型定义为双精度型。但是,XPath 规范还提供了返回 Integer 类型的函数。为了方便此类操作,XPath API 允许在 evaluateExpression 方法中使用 Integer 和 Long,例如以下代码:

   int count = xpath.evaluateExpression("count(/widgets/widget)", document, Integer.class);
 
自从:
1.5