【发布时间】:2014-03-04 11:00:06
【问题描述】:
最初我有这个文件。
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<owl:Class />
<owl:Class />
<owl:ObjectProperty />
<Situation:Situation rdf:about"http://localhost/rdf#situa0">
<Situation:composedBy />
</Situation:Situation>
</rdf:RDF>
我的目标是使用 xPath "RDF/Situation" 提取节点 Situation 及其内容 ...
<Situation:Situation rdf:about"http://localhost/rdf#situa0">
<Situation:composedBy />
</Situation:Situation>
我在Java How to extract a complete XML block 中找到了一个很好的例子。
由于我使用命名空间和预定义标签,因此我将标签名称更改为我自己的名称。
这是我的代码
public static void main(String... args) throws Exception {
String xml = "<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"><owl:Class /><owl:Class /><owl:ObjectProperty /><Situation:Situation rdf:about=\"http://localhost/rdf#situa0\" ><Situation:composedBy /></Situation:Situation></rdf:RDF>";
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
Document doc = dbf.newDocumentBuilder().parse(
new InputSource(new StringReader(xml)));
XPath xPath = XPathFactory.newInstance().newXPath();
Node result = (Node) xPath.evaluate("RDF/Situation", doc, XPathConstants.NODE);
System.out.println(nodeToString(result));
}
private static String nodeToString(Node node) throws TransformerException {
StringWriter buf = new StringWriter();
Transformer xform = TransformerFactory.newInstance().newTransformer();
xform.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
xform.transform(new DOMSource(node), new StreamResult(buf));
return (buf.toString());
}
我的目标已经实现了 90%,但是我有一个问题,Situation 标签有一个带有前缀 rdf 的属性(如果我删除前缀,并且即使我在根元素中添加了 rdf xmlns,代码也可以工作)
<Situation:Situation rdf:about="http://localhost/rdf#situa0">
我收到了这个错误
ERROR: 'The namespace prefix' rdf 'has not been declared.'
Exception in thread "main" javax.xml.transform.TransformerException: java.lang.RuntimeException: Namespace prefix 'rdf' has not been declared.
com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform at (Unknown Source)
com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform at (Unknown Source)
我像@Ian Roberts 提到的那样添加了dbf.setNamespaceAware(true),所以我在询问owl & Situation 命名空间时遇到了其他错误,在将它添加到根标签后,我在输出中什么也没有,也没有错误。问题是什么 ??问题是变量result,这次是null,所以xPath查询有问题..
我试图在另一个地方查看查询结果,它在an online xPath tester 中运行良好。
那么问题出在哪里??
有没有其他方法可以像这个工作一样????
谢谢 :)
【问题讨论】:
-
那个 XML 不是命名空间格式良好的——你使用了两个你没有声明的前缀,
owl:和Situation:——所以你不能使用 XPath 来处理它。 -
我只需要提取节点“Situation”,我删除了 rdf 前缀,它工作正常。
-
它似乎可以工作,因为您正在使用非命名空间感知解析器解析 XML(您必须在调用 @ 之前在
dbf上调用setNamespaceAware(true)987654336@ 以使其知道命名空间),但这是特定于实现的。 XPath 仅在命名空间格式良好的 XML 上定义,如果您碰巧将另一个 XPath 实现引入您的类路径(例如 Saxon),您的代码可能会停止工作。 -
如果你配置了
NamespaceContext,你可以用xpath来做这件事,但是如果你是从一个DOM文档开始的,那么只使用DOM API并做doc.getElementsByTagNameNS("http://localhost/Situation.owl#", "Situation")会简单得多。或者更好的是,使用适当的 RDF API,例如 Jena,因为将 RDF 视为 XML 是非常脆弱的(有许多不同的方法可以在 XML 中表示相同的 RDF 图)。 -
请注意,尝试使用 XML 处理工具处理 RDF 通常不是一个好主意,因为同一个 RDF 图可能有许多 XML 序列化。请参阅How to access OWL documents using XPath in Java? 和this answer 了解更多详情。