Pull string from RDF node

时光毁灭记忆、已成空白 提交于 2019-12-24 03:13:02

问题


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

    }

}

回答1:


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.




回答2:


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.




回答3:


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.



来源:https://stackoverflow.com/questions/26403868/pull-string-from-rdf-node

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!