2
votes

Im trying to get the data in a more readable format when using a SPARQL query with Jena, however I have no idea how to extract the data in a proper way. As for now, the output is:

"http://www.w3.org/TR/2003/PR-owl-guide-20031209/wine#SaucelitoCanyon"

Where instead would like to just have the "SaucelitoCanyon" as a output.

public JenaQuery() {

    String wineRegion = "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>\n"
            + "PREFIX owl: <http://www.w3.org/2002/07/owl#>\n"
            + "PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>\n"
            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>\n"
            + "PREFIX wine:<http://www.w3.org/TR/2003/PR-owl-guide-20031209/wine#>\n"
            + "SELECT  ?region ?winery \n"
            + "WHERE {?wine wine:locatedIn ?region . \n"
            + "?region wine:locatedIn wine:CaliforniaRegion  . \n"
            + "?wine wine:hasMaker  ?winery}";

    String inputFileName = "wine.rdf";
    // create an empty model

    Model model = ModelFactory.createDefaultModel();
    // use the FileManager to find the input file
    InputStream in;
    in = FileManager.get().open(inputFileName);
    if (in == null) {
        throw new IllegalArgumentException(
                "File: " + inputFileName + " not found");
    }
    // read the RDF/XML file
    model.read(in, null);
    try (QueryExecution qexec = QueryExecutionFactory.create(wineRegion, model)) {

        ResultSet results = qexec.execSelect();

        while (results.hasNext()) {
            QuerySolution row = results.next();
            RDFNode winery = row.get("winery");
            System.out.println(winery);
        }

        qexec.close();

    }

}
3
You can do this all in the SPARQL query, as described in my answer to retrieving the class name of a specific subclass in owl.Joshua Taylor

3 Answers

5
votes

Since you've already got the prefix in the SPARQL query, you can use the strafter and str functions to convert the URIs to strings and take the suffix after the prefix. In the following, I've used values ?winery { ... } to bind ?winery to a particular URI, but your query already takes care of that. The important part is the bind afterward that takes care of the string processing.

PREFIX wine: <http://www.w3.org/TR/2003/PR-owl-guide-20031209/wine#>
SELECT ?winery ?localname
WHERE {
  values ?winery { wine:SomeWinery }
  bind( strafter(str(?winery),str(wine:)) as ?localname )
}
winery                                                            localname
<http://www.w3.org/TR/2003/PR-owl-guide-20031209/wine#SomeWinery> "SomeWinery"

That said, in well structured ontologies, individuals will often have an rdfs:label that should provide a string label for an individual. When it's available, you might consider simply retrieving that value. E.g.,

SELECT ?winery ?name
WHERE {
  #-- ... 
  ?winery rdfs:label ?name
}

This was previously described in my answer to retrieving the class name of a specific subclass in owl, but that question didn't involve Jena, so it's not quite a duplicate, even though the same SPARQL-based solution works.

4
votes

Note that in Jena you have two nice Java sources for nice qName conversions: Prologue and PrefixMapping. Your Model is a PrefixMapping and your Query (if you compiled it) is a Prologue. Both of these objects have a #shortForm(String uri) method that you can use to get a shortened form of a URI without modifying your query.

If your model has prefixes defined in it, you can use PrefixMapping#shortForm(String) as follows (pseudocode):

final Model m = // TODO
final String shortForm = m.shortForm(winery.asResource().getURI());

If you compile your Query using QueryFactory, then you can use query-specific prefixes in Prologue#shortForm(String) as follows (pseudocode):

final Query q = QueryFactory.create(/* TODO */);   
final String shortForm = q.shortForm(winery.asResource().getURI());

It's then worth knowing that this will give you a name of the form wine:SaucelitoCanyon (if the wine: prefix is defined, otherwise it will give you http://www.w3.org/TR/2003/PR-owl-guide-20031209/wine#SaucelitoCanyon). You would still need to split the resulting string to get just the local name which may be a little verbose:

final String longName = winery.asResource().getURI();
final String localName;
if(  !shortForm.equals(longName) ) {
    localName = shortForm.split(":")[1];
}
else {
    throw new IllegalStateException("could not resolve prefix for "+longName);
}

This provides you a guarantee that you are using the local name associated with some prefix in your model or your query.

3
votes

You can use the "getLocalName" function in Jena. That will get you the local name of the resource, which is what you seem to be looking for:

QuerySolution row = results.next();
RDFNode winery = row.get("winery");
String r = winery.asNode().getLocalName();
System.out.println(r);

Alternatively you can get the node as a resource directly, which saves you one line of code:

String r = row.getResource("winery").getLocalName();

Edit: as stated in the comments below, this answer will only be valid if your prefix "wine" is as you have declared it in your code. Otherwise the results may not be as desired.