我有一些大致如下的XML:
<project type="mankind">
<suggestion>Build the enterprise</suggestion>
<suggestion>Learn Esperanto</suggestion>
<problem>Solve world hunger</suggestion>
<discussion>Do Vulcans exist</discussion>
</project>
我想使用XPath来查找二级元素的名称(可能有我不知道的元素,并且使用Java)。这是我试过的代码:
public NodeList xpath2NodeList(Document doc, String xPathString) throws XPathExpressionException {
XPath xpath = XPathFactory.newInstance().newXPath();
MagicNamespaceContext nsc = new MagicNamespaceContext();
xpath.setNamespaceContext(nsc);
Object exprResult = xpath.evaluate(xPathString, doc, XPathConstants.NODESET);
return (NodeList) exprResult;
}
我的XPath是/project/*/name()
。我收到错误:
javax.xml.transform.TransformerException:未知节点类型:名称
像/project/suggestion
这样的查询按预期工作。我错过了什么?我想获得一个带有标签名称的列表。
答案 0 :(得分:2)
Java6(不要问)。
我认为您的实现仅支持XPath 1.0。如果这是真的,只有以下方法可行:
"name(/project/*)"
原因是在XPath 1.0模型中,您不能使用函数(如name()
)作为路径表达式中的一个步骤。您的代码抛出异常,在这种情况下,处理器会错误您的函数name()
以获取未知的节点测试(如comment()
)。但是使用路径表达式作为name()
函数的参数没有任何问题。
不幸的是,如果一个只能处理单个节点作为参数的XPath 1.0函数被赋予一系列节点,则只使用第一个节点。因此,您可能只会获得第一个元素名称。
XPath 1.0的操作能力非常有限,通常解决此类问题的最简单方法是使用XPath作为查询语言的高级语言(在您的Java案例中)。或者换一种方式:编写一个XPath表达式来检索所有相关节点并迭代结果,返回元素名称,用Java表示。
使用XPath 2.0,您的初始查询会没问题。另请参阅this related question。
答案 1 :(得分:1)
以下代码可能会回答您的原始问题。
package com.example.xpath;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
public class XPathReader {
static XPath xPath = XPathFactory.newInstance().newXPath();
public static void main(String[] args) {
try {
FileInputStream file = new FileInputStream(new File("c:/mankind.xml"));
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = builderFactory.newDocumentBuilder();
Document xmlDocument = builder.parse(file);
XPathExpression expr = xPath.compile("//project/*");
NodeList list= (NodeList) expr.evaluate(xmlDocument, XPathConstants.NODESET);
for (int i = 0; i < list.getLength(); i++) {
Node node = list.item(i);
System.out.println(node.getNodeName() + "=" + node.getTextContent());
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (XPathExpressionException e) {
e.printStackTrace();
}
}
}
假设输入已得到纠正(Solve world hunger),代码应该打印出来:
建议=建立企业
建议=学习世界语
问题=解决世界饥饿问题
讨论=存在Vulcans