How to access OWL documents using XPath in Java?
Asked Answered
R

3

6

I am having an OWL document in the form of an XML file. I want to extract elements from this document. My code works for simple XML documents, but it does not work with OWL XML documents.

I was actually looking to get this element: /rdf:RDF/owl:Ontology/rdfs:label, for which I did this:

 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();

I also tried extracting only the rdfs:label element this way:

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

But this nodelist is empty.

Please let me know where I am going wrong. I am using Java XPath API.

Raney answered 11/6, 2013 at 5:11 Comment(3)
You've gone wrong by using XPath to work with RDF. You should be using an RDF library. It's going to be easier to work with and less error prone than this approach, both Jena and Sesame are good options.Cantaloupe
@Michael: You are right. But, In my architecture, I am using xpath to refer to the element in the ontology. This xpath reference is stored in the db(as a value of table attribute). Each db fields could refer to different elements from different ontologies. I am then accessing the db, getting the element name, and then am using jena for getting the datamodel for this ontology reference element. What do you suggest?Raney
Frankly, that sounds like a bit of a Rube Goldberg machine. You can use SPARQL to access elements in an RDF model, which is a better approach than XPath queries you're getting out of a relational db. I'm not sure why you have a RDBMS involved, but I suspect your design would be better if you simply used a relational db or used an RDF database.Cantaloupe
M
2

as xpath does not know the namespaces you are using. try using:

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

local name will ignore the namespaces and will work (for the first instance of this that it finds)

Moskow answered 11/6, 2013 at 5:15 Comment(5)
Thanks, this works! Isnt there a cleaner solution? I need to access many such queries for accessing different parts of the ontology.Raney
There is a cleaner solution, for that you have to implement a Name NameSpaceContext for you.Cateran
to do that have a look at this questions answers #6390839Moskow
@SeanF: How do we access attributes using the local-name?Raney
same thing would be .../*[local-name()='label']/@attributenameMoskow
L
15

Don't query RDF (or OWL) with XPath

There's already an accepted answer, but I wanted to elaborate on @Michael's comment on the question. It's a very bad idea to try to work with RDF as XML (and hence, the RDF serialization of an OWL ontology), and the reason for that is very simple: the same RDF graph can be serialized as lots of different XML documents. In the question, all that's being asked for the is rdfs:label of an owl:Ontology element, so how much could go wrong? Well, here are two serializations of the ontology.

The first is fairly human readable, and was generated by the OWL API when I saved the ontology using the Protégé ontology editor. The query in the accepted answer would work on this, I think.

<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>

Here is the same RDF graph using fewer of the fancy features available in the RDF/XML encoding. This is the same RDF graph, and thus the same OWL ontology. However, there is no owl:Ontology XML element here, and the XPath query will fail.

<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>

You cannot reliably query an RDF graph in RDF/XML serialization by using typical XML-processing techniques.

Query RDF with SPARQL

Well, if we cannot query reliably query RDF with XPath, what are we supposed to use? The standard query language for RDF is SPARQL. RDF is a graph-based representation, and SPARQL queries include graph patterns that can match a graph.

In this case, the pattern that we want to match in a graph consists of two triples. A triple is a 3-tuple of the form [subject,predicate,object]. Both triples have the same subject.

  • The first triple says that the subject is of type owl:Ontology. The relationship “is of type” is rdf:type, so the first triple is [?something,rdf:type,owl:Ontology].
  • The second triple says that subject (now known to be an ontology) has an rdfs:label, and that's the value that we're interested in. The corresponding triple is [?something,rdfs:label,?label].

In SPARQL, after defining the necessary prefixes, we can write the following query.

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 .                                                                                                                                                                
}

(Note that because rdf:type is so common, SPARQL includes a as an abbreviation for it. The notation s p1 o1; p2 o2 . is just shorthand for the two-triple pattern s p1 o1 . s p2 o2 ..)

You can run SPARQL queries against your model in Jena either programmatically, or using the command line tools. If you do it programmatically, it is fairly easy to get the results out. To confirm that this query gets the value we're interested in, we can use Jena's command line for arq to test it out.

$ arq  --data labelledOnt.owl --query getLabel.sparql
--------------------------------------
| label                              |
======================================
| "Here is a label on the Ontology." |
--------------------------------------
Launderette answered 11/6, 2013 at 19:42 Comment(11)
You can also read this answer while replacing regex by XPath and HTML by RDF.Launderette
You are right. But, In my architecture, I am using xpath to refer to the element in the ontology. This xpath reference is stored in the db(as a value of table attribute). Each db fields could refer to different elements from different ontologies. I am then accessing the db, getting the element name, and then am using jena for getting the datamodel for this ontology reference element. What do you suggest?Raney
@Raney Can you clarify a little bit more? I haven't done much XPath work, so I don't know all the terminology. When you say that the XPath reference is stored in the database, do you mean that the XPath query (something like /rdf:RDF/owl:Ontology/rdfs:label) is stored in the DB, or the result is stored in the DB?Launderette
@Raney Regardless, the query that you're running in this case asks for the rdfs:label of something which is an owl:Ontology. You can write that sort of query in SPARQL as SELECT ?label WHERE { ?o rdf:type owl:Ontology ; rdfs:label ?label }, and then you'll get the labels of the ontologies in the model. This query would work on either of the serializations of the model shown above, because it's based on the RDF graph structure, no the XML structure. (I'll update my answer.)Launderette
I've updated my answer to show how you can get the same data from the model using a SPARQL query.Launderette
Thanks a lot Joshua. This was a very useful edit. I am now seriously looking to change from XPath to SPARQL.In my previous comment, I meant that the Xpath query itself(and not the result) is stored in the db. Now, going by SPARQL way, as I understood it, I need to also store PREfIX in my db along with SPARQL query. Right? What would be the best way to do that? I can use jena as a reasoner for sparql queries.Raney
@Raney I'm glad to hear that you're considering switching :). It is very easy to get XML-based solutions working in a “good-enough” way, especially if the data seems to have some structural similarity, but it is very brittle; if the version of the library that produces the RDF/XML changes, it might produce equivalent RDF, but different XML. It can be a very confusing problem to try to track down. In SPARQL, the PREFIX lines are part of the query, and let you write things like owl:Ontology, but you could still write that in a long form, viz., <http://www.w3.org/2002/07/owl#Ontology>Launderette
@Raney … instead. Even so, since most of the prefixes are pretty standard, it would probably be OK to store just the SELECT … WHERE { … }, and add the standard prefixes when you run the query. I suppose it depends on whether you want the database contents to contain complete SPARQL queries, or pieces that (are documented to) fit together into a template in a particular (and well documented) way.Launderette
Sorry, but could you explain the equivalence between the two XML fragments? I looked in OWL 2 Web Ontology Language Mapping to RDF Graphs, and elsewhere, and came up empty.Surfboarding
@EdStaub Sure, when you have a resource x, that will typically appear as <rdf:Description rdf:about="x">…</rdf:Description> where x's properties are given as child elements of that element. However, because x rdf:type y are so common, you can abbreviate <rdf:Description rdf:about="x"><rdf:type rdf:resource="y">…</rdf:Description> as <y rdf:about="x">…</y>. That doesn't actually have anything to do with OWL; it's just part of RDF/XML. See 2.13 Typed Node Elements. Examples 14 and 15 show both ways.Launderette
@EdStaub That's just one of many places where there can be variation in how an RDF graph is serialized in RDF/XML.Launderette
M
2

as xpath does not know the namespaces you are using. try using:

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

local name will ignore the namespaces and will work (for the first instance of this that it finds)

Moskow answered 11/6, 2013 at 5:15 Comment(5)
Thanks, this works! Isnt there a cleaner solution? I need to access many such queries for accessing different parts of the ontology.Raney
There is a cleaner solution, for that you have to implement a Name NameSpaceContext for you.Cateran
to do that have a look at this questions answers #6390839Moskow
@SeanF: How do we access attributes using the local-name?Raney
same thing would be .../*[local-name()='label']/@attributenameMoskow
C
1

You would be able to use namespaces in query if you implement javax.xml.namespace.NamespaceContext for yourself. Please have a look at this answer https://mcmap.net/q/1631986/-xpath-xml-namespaces-and-java, this explains how to get it done.

Cateran answered 11/6, 2013 at 5:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.