无法使用XPath从标记中提取所需的属性值

时间:2018-11-02 16:40:01

标签: java xpath xhtml

我有一个如下所示的XHTML:

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta name="sample" content="Just for sample"/>
    <title/>
  </head>
  <body>
    <h1>Sample Heading</h1>
    <p align="left">XHTML and HTML are relatives.<a href="http://www.google.com">Google</a>
    </p>
  </body>
</html>

我想使用Java中的XPath表达式从align中提取<p>的属性值。因此,我尝试使用以下代码:

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);


DocumentBuilder builder = factory.newDocumentBuilder();
    Document doc = builder.parse("TestFile.xhtml");

//Create XPath

XPathFactory xpathfactory = XPathFactory.newInstance();
XPath Inst= xpathfactory.newXPath();
NodeList nodes = (NodeList)Inst.evaluate("//p/@align",doc,XPathConstants.NODESET);
    for (int i = 0; i < nodes.getLength(); ++i) 
   {
            Element e = (Element) nodes.item(i);
            System.out.println(e);
    }

在Java代码中。但是我没有任何输出。即使我只写//body,也不会提取任何东西。谁能告诉我我在做什么错?代码中的任何编辑都会有所帮助。

1 个答案:

答案 0 :(得分:0)

您的XHTML中没有名为p的元素,即使它看起来可能如此。

在XML中使用xmlns属性时,您声明带有该属性的元素以及所有后代元素都在该名称空间中(除非被其他名称空间声明显式覆盖)。

因此,根元素未命名为html,它实际上是'http://www.w3.org/1999/xhtml“名称空间中的'html。'html部分称为“本地部分”。本地名称和名称空间URI统称为QName

按照惯例,这是通过将名称空间URI放在花括号中作为前缀来编写的,因此为了便于讨论,根元素为{http://www.w3.org/1999/xhtml}html,而您要查找的元素为{http://www.w3.org/1999/xhtml}p

处理此问题的一种方法是使用install a NamespaceContext,但是由于我一直难以理解的原因,Java SE没有NamespaceContext的公共标准实现,这使得设置繁琐。

一种更简单的方法是定制XPath表达式以仅基于每个元素的本地部分来搜索元素:

Inst.evaluate("//*[local-name()='p']/@align", doc, XPathConstants.NODESET);

如果您使用的是DocumentBuilderFactory,请记住在创建DocumentBuilder之前在其上调用setNamespaceAware(true)