Java XPath normalize-space()返回规范化字符串序列

Java XPath normalize-space()返回规范化字符串序列,java,xml,xpath,Java,Xml,Xpath,我需要使用XPath函数normalized-space()来规范化我要从XHTML文档中提取的文本: 我使用以下表达式: //*[@slot="address"]/normalize-space(.) 这在我用来测试XPath表达式的工具Qizx Studio中非常有效 let $doc := doc('http://test.anahnarciso.com/clean_bigbook_0.html') return $doc//*[@slot="address"]/norm

我需要使用XPath函数normalized-space()来规范化我要从XHTML文档中提取的文本:

我使用以下表达式:

//*[@slot="address"]/normalize-space(.)
这在我用来测试XPath表达式的工具Qizx Studio中非常有效

    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);
但最后一行抛出了一个异常:

无法将XPath值转换为Java对象:所需类为org.w3c.dom.NodeList;提供的值的类型为xs:string

显然,我应该更改XPathConstants.NODESET的
;我尝试了XPathConstants.STRING,但它只返回序列的第一个元素

如何获得字符串数组之类的内容


提前感谢。

这取决于您使用的XPath版本。查看这篇文章,希望它能回答您的问题:祝您好运。

正如您所指出的,XPath 2.0表达式
/*[@slot=“address”]/normalize space(.)
返回一个字符串序列。JAXP
XPathConstants
类不支持此返回类型,因为JAXP接口的设计不支持XPath 2.0

这给您留下了两个选择:

  • 使用具有或可以
  • 仅使用XPath 1.0表达式。例如,在您的情况下,您可以简单地选择目标节点:

    //*[@slot="address"]
    
    然后迭代生成的节点集,将结果收集到数组或
    列表中


  • 请注意,区分用于计算表达式的处理器和用于启动计算的接口非常重要。

    表达式:

    //*[@slot="address"]/normalize-space(.)
    
    在语法上是合法的(并且实际上是有用的)XPath2.0表达式

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

    事实上,不可能编写一个XPath 1.0表达式,其计算结果是所需的字符串集


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

    您的表达式在XPath 2.0中工作,但在XPath 1.0(在Java中使用)中是非法的-它应该是
    规范化空间(//*[@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));
    }
    
    XPath=XPathFactory.newInstance().newXPath();
    xpathexpressionexpr;
    String select=“//*[@slot='address']”;
    expr=xpath.compile(选择);
    NodeList result=(NodeList)expr.evaluate(输入,XPathConstants.NODESET);
    字符串normalize=“规范化空间(.)”;
    expr=xpath.compile(规范化);
    int length=result.getLength();
    for(int i=0;i

    …输出的正是您给定的输出。

    就是这样,谢谢。我搜索了类似的问题,但没有找到。看起来我最终还是要使用Saxon…谢谢,您的回答非常有用。谢谢您提供的信息,我不知道XPath 1.0如此有限。我已经尝试过Saxon,但我发现它比JAXP复杂一点。@anahnarciso:如果您的意思是XPath 2.0比JAXP提供接口的XPath(1.0)版本更复杂,这可能是真的。另一方面,如果你的意思是萨克森更难调用,我不太确定。我每天都用Saxon执行许多转换——从命令行调用Saxon是很简单的。我的意思是,因为我太习惯于JAXP了,我试图避免使用另一个外部库。我找到的最好的Saxon Java代码示例是官方网站上提供的示例。你知道关于Saxon的其他有用的资源/教程吗?