Java 从RDF节点提取字符串

Java 从RDF节点提取字符串,java,sparql,jena,owl,ontology,Java,Sparql,Jena,Owl,Ontology,在使用Jena的SPARQL查询时,我试图以更可读的格式获取数据,但是我不知道如何以正确的方式提取数据。 就目前而言,结果是: “” 相反,我们希望将“SaucelitoCanyon”作为输出 public JenaQuery() { String wineRegion = "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>\n" + "PREFIX owl: <http://w

在使用Jena的SPARQL查询时,我试图以更可读的格式获取数据,但是我不知道如何以正确的方式提取数据。 就目前而言,结果是:

“”

相反,我们希望将“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();

    }

}
public-JenaQuery(){
String wineRegion=“前缀rdf:\n”
+“前缀owl:\n”
+“前缀xsd:\n”
+“前缀rdfs:\n”
+“前缀酒:\n”
+“选择?地区?酿酒厂\n”
+“何处{?葡萄酒:位于?地区。\n”
+“?地区葡萄酒:地点葡萄酒:加州地区。\n”
+“?葡萄酒:hasMaker?winery}”;
字符串inputFileName=“wine.rdf”;
//创建一个空模型
模型模型=ModelFactory.createDefaultModel();
//使用文件管理器查找输入文件
输入流输入;
in=FileManager.get().open(inputFileName);
if(in==null){
抛出新的IllegalArgumentException(
“文件:”+inputFileName+“未找到”);
}
//读取RDF/XML文件
model.read(in,null);
try(QueryExecution qexec=QueryExecutionFactory.create(wineRegion,model)){
ResultSet results=qexec.execSelect();
while(results.hasNext()){
QuerySolution行=results.next();
RDFNode winery=row.get(“winery”);
系统输出打印(酿酒厂);
}
qexec.close();
}
}
您可以在耶拿使用。这将为您获取资源的本地名称,这似乎是您要查找的:

QuerySolution row = results.next();
RDFNode winery = row.get("winery");
String r = winery.asNode().getLocalName();
System.out.println(r);
或者,您可以直接将节点作为资源获取,这将为您节省一行代码:

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

编辑:如下面的评论所述,只有当您的前缀“wine”与您在代码中声明的前缀相同时,此答案才有效。否则,结果可能不符合要求。

因为您已经在SPARQL查询中获得了前缀,所以可以使用strafterstr函数将URI转换为字符串,并在前缀后加上后缀。在下面,我使用了
values?winery{…}
?winery
绑定到一个特定的URI,但是您的查询已经解决了这个问题。重要的部分是负责字符串处理的绑定

前缀葡萄酒:
选择?winery?localname
在哪里{
价值观?酒庄{葡萄酒:某个酒庄}
绑定(strafter(str(?winery),str(wine:)为?localname)
}
winery localname
“某个酒厂”
也就是说,在结构良好的本体中,个体通常会有一个rdfs:label,它应该为个体提供一个字符串标签。当它可用时,您可以考虑简单地检索该值。例如:

选择酿酒厂名称
在哪里{
#-- ... 
?酒厂rdfs:标签?名称
}

这在之前的to中已经描述过,但是这个问题不涉及Jena,因此它不是一个完全重复的问题,即使相同的基于SPARQL的解决方案也可以工作。

请注意,在Jena中,有两个很好的Java源代码可以进行很好的qName转换:
Prologue
PrefixMapping
。您的
模型
是一个
前缀映射
,您的
查询
(如果您编译了它)是一个
序言
。这两个对象都有一个
#shortForm(stringuri)
方法,您可以使用该方法获得uri的缩写形式,而无需修改查询

如果您的模型中定义了前缀,则可以按如下方式使用(伪代码):

final Model m=//TODO
最后一个字符串shortForm=m.shortForm(winery.asResource().getURI());
如果使用
QueryFactory
编译您的
查询
,则可以使用以下特定于查询的前缀(伪代码):

然后值得知道的是,这将为您提供一个形式为
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);
}

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

给定的URI可以分解为任意数量的前缀和本地名称。例如,您可以拆分
http://example.org/foobar
作为ex:foobar、ex1:oobar、ex2:obar、ex3:bar、ex4:ar、ex5:r,给出了适当的ex、ex1、ex2等声明。Jena的getLocalName应用了一种启发式方法,但不能保证给出一种基于原始文件前缀声明的方法。因为这是一个SPARQL查询,其中查询中有一个前缀,所以使用该前缀并在查询中拆分字符串可能更有意义。我假设他在代码中有前缀。我会更新我的答案,反映你的评论。谢谢您可以在SPARQL查询中完成这一切,如到中所述。谢谢!我会试试这个。我只是遇到了一些我无法解释的奇怪的事情。当将地区从加利福尼亚地区更改为任何其他地区时,我不会从查询中得到任何结果。我不太明白,因为我可以看到葡萄酒本体中的其他区域。我还刚刚开始使用SPARQL和Jena,所以我很难理解我做的是什么以及是否正确。str(wine:):不错,我不知道在SPARQL字符串中可以使用前缀functions@thomas这不是前缀本身,而是IRI。你可以用葡萄酒:foo;这只是使用前缀中的IRI,没有后缀。
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);
}