JavaScript

JavaScript 知识量:26 - 101 - 483

21.2 对XPath的支持><

DOM Level 3 XPath- 21.2.1 -

DOM Level 3 XPath规范定义了使用XPath表达式对DOM(Document Object Model)进行查询的接口。XPath,或XML路径语言,是一种在XML文档中查找信息的语言。XPath可以在XML文档中进行导航,并可用于在DOM树中定位节点。

DOM Level 3 XPath规范引入了两个主要的接口:XPathEvaluator和XPathResult。

  • XPathEvaluator:这个接口提供了用于执行XPath表达式的功能。它包括一个方法,evaluate(),该方法接收一个XPath表达式、一个上下文节点和一个命名空间管理器,然后返回一个XPathResult对象。

  • XPathResult:这个接口表示XPath查询的结果。它包括一些方法,如getNodeValue()和getNumberValue(),可以用来获取查询结果的值。

这些接口使得开发者可以在DOM中执行XPath表达式,从而找到特定的节点或者获取其他有关DOM的信息。

单个节点结果- 21.2.2 -

XPathResult接口表示XPath表达式的结果。它可以是一个节点,也可以是一个节点列表。如果XPath表达式的结果是一个单一节点,那么可以通过调用result.singleNodeValue来获取这个节点。

如果使用document.evaluate方法执行XPath表达式,并希望得到的结果是第一个匹配的节点,可以将XPathResult.FIRST_ORDERED_NODE_TYPE作为结果的类型参数传递给evaluate方法。

下面是一个示例代码:

var xpath = '//div'; // XPath表达式  
var context = document.createXPathResult(xpath, document);  
var resultType = XPathResult.FIRST_ORDERED_NODE_TYPE;  
var node = context.iterateNext();  
  
if (node) {  
    console.log("匹配的第一个节点:", node);  
} else {  
    console.log("没有找到匹配的节点。");  
}

在这个示例中,使用document.createXPathResult方法创建一个XPath结果对象,并指定了要查找的元素(这里是div)。然后,将结果类型设置为XPathResult.FIRST_ORDERED_NODE_TYPE,并通过调用iterateNext方法来获取匹配的第一个节点。如果找到匹配的节点,它将打印出来;否则,它将打印一条消息表示没有找到匹配的节点。

简单类型结果- 21.2.3 -

XPathResult接口表示XPath表达式的结果。它可以是以下类型之一:

  • NUMBER_TYPE(数字类型)

  • STRING_TYPE(字符串类型)

  • BOOLEAN_TYPE(布尔类型)

  • UNORDERED_NODE_ITERATOR_TYPE(无序节点迭代器类型)

  • ORDERED_NODE_ITERATOR_TYPE(有序节点迭代器类型)

  • UNORDERED_NODE_SNAPSHOT_TYPE(无序节点快照类型)

  • ORDERED_NODE_SNAPSHOT_TYPE(有序节点快照类型)

  • ANY_UNORDERED_NODE_TYPE(任何无序节点类型)

  • FIRST_ORDERED_NODE_TYPE(第一个有序节点类型)

如果XPath表达式的结果是布尔值,那么可以通过调用booleanValue属性来获取这个布尔值。类似地,如果结果是数值,那么可以通过调用numberValue属性来获取这个数值;如果结果是字符串,那么可以通过调用stringValue属性来获取这个字符串。以下是一个例子:

var xpath = '//div[@class="myClass"]'; // XPath表达式  
var context = document.createXPathResult(xpath, document);  
var resultType = XPathResult.FIRST_ORDERED_NODE_TYPE;  
var node = context.iterateNext();  
  
if (node) {  
    console.log("匹配的第一个节点:", node);  
    console.log("节点是否存在:", context.booleanValue);  
    console.log("节点值:", context.stringValue); // 如果节点是文本节点,这将返回文本内容;如果节点是元素节点,这通常返回空字符串  
} else {  
    console.log("没有找到匹配的节点。");  
}

在这个例子中,首先使用document.createXPathResult方法创建一个XPath结果对象,并指定了要查找的元素(这里是div元素,其class属性为myClass)。然后,将结果类型设置为XPathResult.FIRST_ORDERED_NODE_TYPE,并通过调用iterateNext方法来获取匹配的第一个节点。如果找到匹配的节点,它将打印出来,然后打印出布尔值(表示节点是否存在)和字符串值(表示节点的文本内容)。如果没有找到匹配的节点,它将打印一条消息表示没有找到匹配的节点。

默认类型结果- 21.2.4 -

在XPath中,当执行一个XPath表达式时,通常会期望返回某种特定类型的结果。XPath允许明确指定希望得到的结果类型,例如布尔值、数值、字符串或节点集。然而,如果没有明确指定结果类型,那么XPath会返回一个默认类型的结果。

这个默认类型的结果取决于XPath表达式。一般来说,如果XPath表达式的结果可以被解析为一个单一的值(例如一个数字或一个字符串),那么返回的结果就是这个值。如果XPath表达式的结果是一组节点(即一个节点集),那么返回的结果就是一个无序的节点迭代器。

下面是一个简单的示例来解释这个概念:

假设有以下的XPath表达式:"hello, world"。这个表达式实际上是一个字符串,因此当执行这个XPath表达式时,会得到这个字符串作为默认类型的结果。

而如果使用以下XPath表达式://div[@class="myClass"],这会返回文档中所有具有class属性为myClass的div元素。因为这会返回一组节点,所以默认类型的结果将是一个无序的节点迭代器。

需要注意的是,可以使用XPathResult.ANY_TYPE类型来让XPath自动选择最合适的类型返回结果。这在希望让XPath自动处理结果类型的情况下非常有用。例如:

var xpath = '//div[@class="myClass"]'; // XPath表达式  
var context = document.createXPathResult(xpath, document);  
var resultType = XPathResult.ANY_TYPE; // 让XPath自动选择结果类型  
var node = context.iterateNext();  
  
if (node) {  
    console.log("匹配的第一个节点:", node);  
    console.log("节点值:", context.stringValue); // 如果节点是文本节点,这将返回文本内容;如果节点是元素节点,这通常返回空字符串  
} else {  
    console.log("没有找到匹配的节点。");  
}

在这个例子中,使用XPathResult.ANY_TYPE作为结果类型,这意味着XPath将自动选择最适合的结果类型。在这种情况下,它选择的是字符串类型,因为查找的是文本内容。

命名空间支持- 21.2.5 -

在处理带有命名空间的XML文档时,XPath表达式需要知道这些命名空间信息以便正确求值。告诉XPathEvaluator命名空间信息的方式有多种,以下是其中几种:

1. 使用declare-prefix语法:可以在XPath表达式中使用declare-prefix语法来声明命名空间的别名,然后使用这个别名来引用命名空间。例如:

declare namespace myns = "http://example.com/myns";  
/myns:element[@myns:attribute='value']

在这个例子中,myns是命名空间的别名,可以在XPath表达式中使用它来引用命名空间。
2. 设置XPathEvaluator的命名空间上下文:可以通过设置XPathEvaluator的命名空间上下文来告诉它命名空间信息。具体实现方式取决于所使用的XPath库,但通常可以创建一个带有命名空间映射的命名空间上下文对象,并将其设置为XPathEvaluator的上下文。例如,在Java中使用DOMXPathEvaluator时,可以使用以下代码设置命名空间上下文:

XPath xpath = XPathFactory.newInstance().newXPath();  
NamespaceContext namespaceContext = new SimpleNamespaceContext();  
namespaceContext.addNamespace("myns", "http://example.com/myns");  
xpath.setNamespaceContext(namespaceContext);

在这个例子中,创建了一个SimpleNamespaceContext对象,并使用addNamespace方法添加命名空间的别名和URI的映射。然后将这个命名空间上下文设置为XPathEvaluator的上下文。
3. 使用前缀树或映射表:另外一种处理命名空间的方式是使用前缀树或映射表来存储命名空间和别名的对应关系。在求值时,将XPath表达式中的命名空间前缀与前缀树或映射表进行匹配,找到对应的命名空间URI,然后根据URI来解析XPath表达式。这种方式需要在预处理阶段对XML文档进行分析,并构建前缀树或映射表。