2014-10-16 75 views
2

我試圖在使用Jena的SPARQL查詢時以更易讀的格式獲取數據,但是我不知道如何以正確的方式提取數據。 至於現在,輸出結果是:從RDF節點拉字符串

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

    } 

} 
+0

您可以在SPARQL查詢中完成此操作,如[我的答案](http://stackoverflow.com/a/20845304/1281433)中所述[檢索owl中特定子類的類名](http ://stackoverflow.com/q/20830056/1281433)。 – 2014-10-16 13:54:50

回答

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

編輯:如下面評論所述,只有當您的前綴「wine」與您在代碼中聲明相同時,此答案纔有效。否則結果可能不符合要求。

+2

給定的URI可以分解爲任意數量的前綴和本地名稱。例如,如果給出ex,ex1,ex2的適當聲明,你可以將'http:// example.org/foobar'拆分爲ex:foobar,ex1:​​oobar,ex2:obar,ex3:bar,ex4:ar,ex5:r等等。Jena的getLocalName應用啓發式,但不能保證給出基於原始文件的前綴聲明。由於這是使用SPARQL,查詢查詢中有前綴的位置,因此只需使用該前綴並在查詢中拆分字符串就可能更有意義。 – 2014-10-16 13:34:23

+0

這是真的。我假設他在代碼中使用了前綴。我會更新我的答案,反映您的評論。謝謝 – 2014-10-16 14:54:13

5

既然你已經有了前綴的SPARQL查詢,你可以使用strafter海峽功能中的URI轉換爲字符串,並採取了後綴,前綴之後。在下面,我使用values ?winery { ... }?winery綁定到特定的URI,但是您的查詢已經處理了該問題。其中重要的部分是綁定後來,照顧字符串處理。

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:標籤應該提供一個單獨的字符串標籤。當它可用時,您可以考慮簡單地檢索該值。例如,

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

my answer先前描述retrieving the class name of a specific subclass in owl,但這個問題不涉及耶拿,所以它不是一個相當重複的,即使相同的基於SPARQL的解決方案工作。

+0

謝謝!我會試試這個。我剛遇到一些我不能解釋的奇怪東西。當將區域從CaliforniaRegion更改爲任何其他區域時,我不會從查詢中獲得任何結果。因爲我可以在Wine本體中看到其他區域,所以我不太明白。我剛剛開始使用SPARQL和Jena,所以我很難理解什麼以及是否正確。 – andreasolsson 2014-10-16 19:09:12

+0

str(wine :):很好,我不知道可以在sparql字符串函數中使用前綴 – ThomasFrancart 2014-10-20 08:53:39

+0

@thomas它不是前綴本身,而是IRI。你可以用wine:foo;這只是使用來自前綴的IRI而沒有後綴。 – 2014-10-20 09:52:37

3

請注意,在Jena中,您有兩個不錯的Java源代碼可用於更好的qName轉換:ProloguePrefixMapping。您的ModelPrefixMapping,您的Query(如果您編譯它)是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); 
} 

這爲您提供您正在使用與您的型號和一些前綴相關聯的本地名稱擔保查詢。