6

我有一个 XML 文件形式的 OWL 文档。我想从此文档中提取元素。我的代码适用于简单的 XML 文档,但不适用于 OWL XML 文档。

我实际上是在寻找这个元素:/rdf:RDF/owl:Ontology/rdfs:label,为此我做了这个:

 DocumentBuilder builder = builderfactory.newDocumentBuilder();
    Document xmlDocument = builder.parse(
            new File(XpathMain.class.getResource("person.xml").getFile()));

    XPathFactory factory = javax.xml.xpath.XPathFactory.newInstance();
    XPath xPath = factory.newXPath();
    XPathExpression xPathExpression = xPath.compile("/rdf:RDF/owl:Ontology/rdfs:label/text()");
    String nameOfTheBook = xPathExpression.evaluate(xmlDocument,XPathConstants.STRING).toString();

我还尝试以这种方式仅提取rdfs:label元素:

 XPathExpression xPathExpression = xPath.compile("//rdfs:label");        
 NodeList nodes = (NodeList) xPathExpression.evaluate(xmlDocument, XPathConstants.NODESET);

但是这个节点列表是空的。

请让我知道我哪里出错了。我正在使用 Java XPath API。

4

3 回答 3

15

不要使用 XPath 查询 RDF(或 OWL)

已经有一个公认的答案,但我想详细说明@Michael对这个问题的评论。尝试将 RDF 作为 XML 使用(因此,OWL 本体的 RDF 序列化)是一个非常糟糕的主意,其原因非常简单:同一个 RDF 图可以序列化为许多不同的 XML 文档。在这个问题中,所有被要求的都是rdfs:label一个owl:Ontology元素,那么有多少可能会出错?好吧,这是本体的两个序列化。

第一个是人类可读的,它是在我使用 Protégé 本体编辑器保存本体时由 OWL API 生成的。我认为,接受的答案中的查询可以解决这个问题。

<rdf:RDF xmlns="http://www.example.com/labelledOnt#"
     xml:base="http://www.example.com/labelledOnt"
     xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
     xmlns:owl="http://www.w3.org/2002/07/owl#"
     xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
     xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
    <owl:Ontology rdf:about="http://www.example.com/labelledOnt">
        <rdfs:label>Here is a label on the Ontology.</rdfs:label>
    </owl:Ontology>
</rdf:RDF>

这是使用较少 RDF/XML 编码中可用的花哨功能的相同RDF 图。这是相同的 RDF 图,因此也是相同的OWL 本体。但是,这里没有 owl:OntologyXML 元素,XPath 查询将失败。

<rdf:RDF
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:owl="http://www.w3.org/2002/07/owl#"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
    xmlns="http://www.example.com/labelledOnt#"
    xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" > 
  <rdf:Description rdf:about="http://www.example.com/labelledOnt">
    <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#Ontology"/>
    <rdfs:label>Here is a label on the Ontology.</rdfs:label>
  </rdf:Description>
</rdf:RDF>

不能使用典型的 XML 处理技术可靠地查询 RDF/XML 序列化中的 RDF 图。

使用 SPARQL 查询 RDF

好吧,如果我们不能用 XPath 可靠地查询 RDF,我们应该使用什么?RDF 的标准查询语言是SPARQL。RDF 是一种基于图的表示,SPARQL 查询包括可以匹配图的图模式。

在这种情况下,我们想要在图中匹配的模式由两个三元组组成。三元组是一个 3 元组的形式[subject,predicate,object]。两个三元组都有相同的主题。

  • 第一个三元组表示主题是 type owl:Ontology。关系“是类型”是rdf:type,所以第一个三元组是[?something,rdf:type,owl:Ontology]
  • 第二个三元组表示主题(现在已知是一个本体)有一个rdfs:label,这就是我们感兴趣的值。对应的三元组是[?something,rdfs:label,?label]

在 SPARQL 中,定义必要的前缀后,我们可以编写以下查询。

PREFIX owl: <http://www.w3.org/2002/07/owl#>                                                                                                                                                   
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>                                                                                                                                           

SELECT ?label WHERE {                                                                                                                                                                          
  ?ontology a owl:Ontology ;                                                                                                                                                                   
            rdfs:label ?label .                                                                                                                                                                
}

(请注意,因为rdf:type很常见,所以 SPARQL 包含a它作为它的缩写。该符号s p1 o1; p2 o2 .只是两个三元组模式的简写s p1 o1 . s p2 o2 .。)

您可以通过编程方式或使用命令行工具对 Jena 中的模型运行 SPARQL 查询。如果您以编程方式执行此操作,则很容易得出结果。为了确认这个查询得到了我们感兴趣的值,我们可以使用 Jena 的命令行arq来测试它。

$ arq  --data labelledOnt.owl --query getLabel.sparql
--------------------------------------
| label                              |
======================================
| "Here is a label on the Ontology." |
--------------------------------------
于 2013-06-11T19:42:08.207 回答
2

因为 xpath 不知道您正在使用的命名空间。尝试使用:

"/*[local-name()='RDF']/*[local-name()='Ontology']/*[local-name()='label']/text()"

本地名称将忽略命名空间并将工作(对于它找到的第一个实例)

于 2013-06-11T05:15:42.993 回答
1

如果您自己实现,您将能够在查询中使用命名空间javax.xml.namespace.NamespaceContext。请看一下这个答案https://stackoverflow.com/a/5466030/1443529,这解释了如何完成它。

于 2013-06-11T05:22:14.990 回答