从RDF节点拉出字符串

时间:2014-10-16 12:00:59

标签: java sparql jena owl ontology

在使用与Jena的SPARQL查询时,我试图以更易读的格式获取数据,但是我不知道如何以正确的方式提取数据。 至于现在,输出是:

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

反而希望将“SaucelitoCanyon”作为输出。

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 个答案:

答案 0 :(得分:5)

由于您已经在SPARQL查询中获得了前缀,因此您可以使用 strafter str 函数将URI转换为字符串并在后面取后缀。字首。在下文中,我使用values ?winery { ... }?winery绑定到特定的URI,但您的查询已经处理了这个问题。重要的部分是 bind 之后负责字符串处理。

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"

也就是说,在结构良好的本体中,个人通常会有一个 rdfs:label ,它应该为个人提供字符串标签。当它可用时,您可以考虑简单地检索该值。例如,

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

之前已在my answerretrieving the class name of a specific subclass in owl中对此进行了描述,但该问题并未涉及Jena,因此即使基于SPARQL的解决方案相同,也不会重复。

答案 1 :(得分:4)

请注意,在Jena中,您有两个很好的Java源代码来实现良好的qName转换:ProloguePrefixMapping。您的ModelPrefixMappingQuery(如果您编译的话)是Prologue。这两个对象都有#shortForm(String uri)方法,您可以使用它来获取缩写形式的URI而无需修改查询。

如果您的模型中定义了前缀,则可以使用PrefixMapping#shortForm(String),如下所示(伪代码):

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

如果您使用Query编译QueryFactory,那么您可以在Prologue#shortForm(String)中使用查询特定的前缀,如下所示(伪代码):

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

然后值得知道,这将为您提供wine:SaucelitoCanyon形式的名称(如果定义了wine:前缀,否则它将为您提供http://www.w3.org/TR/2003/PR-owl-guide-20031209/wine#SaucelitoCanyon)。您仍然需要拆分结果字符串以获取本地名称,这可能有点冗长:

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

这可以保证您使用与模型或查询中的某些前缀关联的本地名称。

答案 2 :(得分:3)

您可以使用耶拿的"getLocalName" function。这将获得资源的本地名称,这是您似乎正在寻找的:

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

或者,您可以直接将节点作为资源获取,这样可以节省一行代码:

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

编辑:如下面的评论中所述,此答案仅在您的前缀&#34; wine&#34;就像你在代码中声明它一样。否则结果可能不是所希望的。