XPath normalize-space()返回一系列规范化字符串

时间:2012-07-07 20:25:48

标签: java xml xpath

我需要使用XPath函数normalized-space()来规范化我要从XHTML文档中提取的文本:http://test.anahnarciso.com/clean_bigbook_0.html

我正在使用以下表达式:

//*[@slot="address"]/normalize-space(.)

在Qizx Studio中完美运行,这是我用来测试XPath表达式的工具。

    let $doc := doc('http://test.anahnarciso.com/clean_bigbook_0.html')
    return $doc//*[@slot="address"]/normalize-space(.)

此简单查询返回xs:string

的序列
144 Hempstead Tpke
403 West St
880 Old Country Rd
8412 164th St
8412 164th St
1 Irving Pl
1622 McDonald Ave
255 Conklin Ave
22011 Hempstead Ave
7909 Queens Blvd
11820 Queens Blvd
1027 Atlantic Ave
1068 Utica Ave
1002 Clintonville St
1002 Clintonville St
1156 Hempstead Tpke
Route 49
10007 Rockaway Blvd
12694 Willets Point Blvd
343 James St

现在,我想在我的Java代码中使用前面的表达式。

String exp = "//*[@slot=\"address"\"]/normalize-space(.)";
XPath xpath = XPathFactory.newInstance().newXPath();
XPathExpression expr = xpath.compile(exp);
Object result = expr.evaluate(doc, XPathConstants.NODESET);

但是最后一行抛出异常:

Cannot convert XPath value to Java object: required class is org.w3c.dom.NodeList; supplied value has type xs:string

很明显,我应该改变XPathConstants.NODESET的某些东西;我尝试了XPathConstants.STRING,但它只返回序列的第一个元素。

如何获得类似Strings数组的内容?

提前致谢。

4 个答案:

答案 0 :(得分:4)

您的表达式在XPath 2.0中有效,但在XPath 1.0(在Java中使用)中是非法的 - 它应该是normalize-space(//*[@slot='address'])

无论如何,在XPath 1.0中,当在节点集上调用normalize-space()时,只会采用第一个节点(按文档顺序)。

为了做你想做的事情,你需要使用兼容XPath 2.0的解析器,或者遍历结果节点集并在每个节点上调用normalize-space()

XPath xpath = XPathFactory.newInstance().newXPath();
XPathExpression expr;

String select = "//*[@slot='address']";
expr = xpath.compile(select);
NodeList result = (NodeList)expr.evaluate(input, XPathConstants.NODESET);

String normalize = "normalize-space(.)";
expr = xpath.compile(normalize);

int length = result.getLength();
for (int i = 0; i < length; i++) {
    System.out.println(expr.evaluate(result.item(i), XPathConstants.STRING));
}

...完全输出您的给定输出。

答案 1 :(得分:3)

这取决于您使用的XPath版本。看看这篇文章,希望它能回答你的问题:Is it possible to apply normalize-space to all nodes XPath expression finds?祝你好运。

答案 2 :(得分:3)

如您所述,XPath 2.0表达式//*[@slot="address"]/normalize-space(.)返回一串字符串。 JAXP XPathConstants类不支持此返回类型,因为JAXP接口不支持XPath 2.0。

这为您提供了两种选择:

  1. 使用具有native interfaces for XPath 2.0convert sequences to a return type supported by JAXP
  2. 的XPath 2.0处理器
  3. 仅使用XPath 1.0表达式。例如,在您的情况下,您只需选择目标节点:

    //*[@slot="address"]
    

    然后迭代生成的节点集,将结果收集到一个数组或List

  4. 请注意,区分用于评估表达式的处理器和用于启动评估的接口非常重要。

答案 3 :(得分:3)

表达式

//*[@slot="address"]/normalize-space(.)

在语法上是合法的(并且实际上是有用的)XPath 2.0表达式。

在XPath 1.0中,相同的表达式在语法上不合法 - 不允许将位置步骤作为函数调用。

实际上,不可能编写单个 XPath 1.0表达式,其结果是所需的字符串集。

您需要在程序中使用实现XPath 2.0的产品 - 例如Saxon 9.x。