Module java.xml

Package javax.xml.xpath


package javax.xml.xpath
提供了一个对象模型中立的API,用于评估XPath表达式并访问评估环境。

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


1. XPath概述

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

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

2. XPath表达式

XPath 表达式由一个位置路径和一个或多个可选的谓词组成。表达式还可以包括XPath变量。

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

     /foo/bar
 

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

     <foo>
         <bar/>
     </foo>
 

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

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

一个特殊的位置路径运算符//选择XML文档中任何深度的节点。以下示例选择文档中所有<bar>元素:

     //bar
 

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

     /foo/*
 

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

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

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

     //foo[@include='true']
 

可以将谓词附加到彼此以进一步细化表达式,例如:

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

3. XPath数据类型

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

  • 布尔值
  • 数字
  • 字符串

3.1 QName类型

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

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

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

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

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

3.2 类型

除了QName类型外,XPath API还通过XPathExpression.evaluateExpression(...)XPath.evaluateExpression(...)方法支持Class类型的使用。XPath数据类型映射到Class类型如下:
  • 布尔值 -- Boolean.class
  • 数字 -- Number.class
  • 字符串 -- String.class
  • 节点集 -- XPathNodes.class
  • 节点 -- Node.class

数字的子类型中,仅支持Double、IntegerLong

3.3 枚举类型

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

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

4. XPath上下文

XPath位置路径可以相对于文档中的特定节点(称为上下文)而言。上下文包括:

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

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

5. 使用XPath API

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

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

     // 将XML解析为W3C文档
     DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
     Document document = builder.parse(new File("/widgets.xml"));

     //获取XPath对象并评估表达式
     XPath xpath = XPathFactory.newInstance().newXPath();
     String expression = "/widgets/widget";
     Node widgetNode = (Node) xpath.evaluate(expression, document, XPathConstants.NODE);

     //或使用evaluateExpression方法
     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);

     //或使用evaluateExpression方法
     Node manufacturerNode = xpath.evaluateExpression(expression, widgetNode, Node.class);
 

在上述示例中,XML文件被读入DOM文档,然后传递给XPath API。以下代码演示了使用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);

     //或使用evaluateExpression方法
     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 数字数据类型被定义为 double。然而,XPath规范还提供了返回 Integer 类型的函数。为了便于这类操作,XPath API 允许在 evaluateExpression 方法中使用 Integer 和 Long,例如以下代码:

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