2013-03-22 59 views
1

我试图构建一个基于给定查询(旧查询 - 我无法更改此)的新查询。不存在'。'导致添加三元组后的解析错误Jena ElementGroup

假设我有一个简单有效的SPARQL查询,SELECT ?s WHERE{ ?s ?p ?o }。比方说,我作出上述查询的耶拿查询对象,并获取查询模式作为ElementGroup在Java中,如下所示:

Query q = QueryFactory.create("SELECT ?s WHERE{ ?s ?p ?o }, Syntax.syntaxSPARQL_11); 
ElementGroup oldQP = (ElementGroup)q.getQueryPattern(); 

我增加新的三元旧查询模式的方式之前,使用以下语法:

Triple t = Triple.create(...); 
oldQP.addTriplePattern(t); 

然而,当你去创建新的查询对象:

Query nq = q.cloneQuery(); 
nq.setQueryPattern(oldQP); 
nq.setQuerySelectType(); 
nq.setQueryResultStar(false); 
nq.addResultVar("s"); 

你有一个查询看起来像

结束
SELECT ?s WHERE{ 
    ?s ?p ?o 
    ?s2 ?p2 ?s. 
} 

因为它不能识别/关心第一个三元组没有以设定对象的QueryPattern的时段结束。这会导致查询运行时出现分析错误...

Encountered " <VAR1> "?s2 "" at line 10, column 3. 
Was expecting one of: 
"graph" ... 
"optional" ... 
"minus" ... 
"bind" ... 
"service" ... 
"let" ... 
"exists" ... 
"not" ... 
"filter" ... 
"{" ... 
"}" ... 
";" ... 
"," ... 
"." ... 

因为这显然是无效的SPARQL。那么,如何避免这个问题呢?如果所有三元组都有关闭期,则不会发生此问题,但我似乎无法找到任何方法来完成此项工作。

谢谢!

回答

0

像你描述下面的代码创建一个查询,将其复制,增加了一个三重模式,版画它并运行这两个查询。你是对的,查询的打印格式缺少一个通常会出现的.。但是,作为RobV pointed out,打印奇怪对查询结果没有任何影响。如果您在实际案例中获得了不同的结果,可以突出显示它与此不同的地方吗?

import com.hp.hpl.jena.graph.Triple; 
import com.hp.hpl.jena.query.Query; 
import com.hp.hpl.jena.query.QueryExecutionFactory; 
import com.hp.hpl.jena.query.QueryFactory; 
import com.hp.hpl.jena.query.ResultSetFormatter; 
import com.hp.hpl.jena.rdf.model.Model; 
import com.hp.hpl.jena.rdf.model.ModelFactory; 
import com.hp.hpl.jena.rdf.model.Property; 
import com.hp.hpl.jena.rdf.model.Resource; 
import com.hp.hpl.jena.sparql.core.Var; 
import com.hp.hpl.jena.sparql.syntax.ElementGroup; 

public class AddTriplePattern { 
    public static void main(String[] args) { 
     // Create the original query 
     final String queryString = "" + 
       "select * where {\n" + 
       " ?s ?p ?o .\n" + 
       "}\n" + 
       ""; 
     final Query query = QueryFactory.create(queryString); 

     // Create the new query and add `?s2 ?p2 ?o2`. Print the new query 
     // before and after adding the triple pattern. Sure enough, after 
     // the modification, the pattern is printed without a `.` between the 
     // triples. The space between the variables is also a bit bigger. 
     final Query newQuery = QueryFactory.create(query); 
     System.out.println("== before ==\n"+newQuery); 
     final ElementGroup eg = (ElementGroup) newQuery.getQueryPattern(); 
     final Triple t = new Triple(Var.alloc("s2"), Var.alloc("p2"), Var.alloc("o2")); 
     eg.addTriplePattern(t); 
     newQuery.setQueryResultStar(false); 
     newQuery.addResultVar("s2"); 
     System.out.println("== after ==\n"+newQuery); 

     // Create a model with a single triple [a, a, a]. 
     final Model model = ModelFactory.createDefaultModel(); 
     final Resource a = model.createResource("urn:ex:a"); 
     model.add(a, a.as(Property.class), a); 

     // Run both the original query and the new query on the model. Both 
     // return the expected results. 
     ResultSetFormatter.out(QueryExecutionFactory.create(query, model).execSelect()); 
     ResultSetFormatter.out(QueryExecutionFactory.create(newQuery, model).execSelect()); 
    } 
} 

的输出是:

== before == 
SELECT * 
WHERE 
    { ?s ?p ?o } 

== after == 
SELECT ?s2 
WHERE 
    { ?s ?p ?o 
    ?s2 ?p2 ?o2 . 
    } 

---------------------------------------- 
| s   | p   | o   | 
======================================== 
| <urn:ex:a> | <urn:ex:a> | <urn:ex:a> | 
---------------------------------------- 
-------------- 
| s2   | 
============== 
| <urn:ex:a> | 
-------------- 
+0

re:Missing。 旧bug - 修正(至少在开发代码库中)。 – AndyS 2013-07-24 20:48:24

+0

@AndyS RobV的答案表明它也是已知的,也是老的。我只是想在这里找到一个完整的工作示例,以满足任何其他人的需求。现在他们可以看到他们应该做什么。 – 2013-07-24 21:20:52

1

我不确定我在这里完全按照你的问题

第二个查询来自哪里?您是否在新查询对象上调用toString(),在这种情况下,这可能是打印查询的内部逻辑中的一个错误。

你还使用什么版本的ARQ?

+0

的System.out.println(nq.serialize()); - 是的,打印新的查询对象。但是做一些调试会产生ElementGroup本身(这里的oldQP)看起来像这样,所以我不相信它是专门打印的。 对不起,我感到困惑。本质上,问题似乎是,当你将三元组添加到看起来像{?s?p?o}的查询模式时,你会得到一个类似于{?s?p?o?s2?p2?s的查询模式。 s3?p3?s2。}等,s.t.第一个三元组和下一个三元组不会被正确的语法分隔(一个'。'字符)。 我使用arq-2.8.5-patched-2.jar我相信。 – 2013-03-22 18:54:39

+1

好的,你的问题很可能是它的一个真正旧版本的ARQ,2.8.5是从2010年7月开始的,当前版本2.10.0于2013年3月发布。如果你真的能够**升级你的依赖。 – RobV 2013-03-22 20:51:07

+1

再次读你的问题,你为什么要把它打印出来并作为一个字符串再解析回来?是不是可以简单地执行你直接创建的新查询对象,从而完全避免这个问题? – RobV 2013-03-22 23:16:01

1

所以我似乎找到了解决方法。 调试和在由

ElementGroup oldQP = (ElementGroup)q.getQueryPattern(); 

我注意到它运动元素对象的ArrayList线创建的ElementGroup对象更接近地寻找后(通过方法ElementGroup.getElements()检索)。在我尝试添加三元组之前(通过ElementGroup.addTriplePattern(...)方法),此列表中唯一的一个是类型ElementPathBlock的对象。好,很酷。

接下来,我尝试通过上面的方法添加的三元,像这样:

Triple t = Triple.create(...); 
oldQP.addTriplePattern(t); 

我注意到,这增加了一个新的ElementTriplesBlock要素的ElementGroup的名单。看来这是罪魁祸首。所以,我的解决办法是不是抢的ElementPathBlock最后一次出现,而三元添加到该对象,而不是将它们添加到ElementGroup(这样就避免了添加新ElementTriplesBlock到ArrayList):

//same as before 
Query q = QueryFactory.create("SELECT ?s WHERE{ ?s ?p ?o }, Syntax.syntaxSPARQL_11); 
Query nq = q.cloneQuery(); 
ElementGroup oldQP = (ElementGroup)q.getQueryPattern(); 
Triple t = Triple.create(Var.alloc("s2"), Var.alloc("p2"), Var.alloc("s)); 

//new 
ElementPathBlock epb; 
int index = -1; 
for(int i=0; i<oldQP.getElements().size(); i++){ 
    if(oldQP.getElements().get(i) instanceof ElementPathBlock){ 
     //...get last index of instanceof ElementPathBlock, if exists. 
     index = i; 
    } 
} 
if(index > -1){ 
    //...found occurence of ElementPathBlock we will add to 
    epb = (ElementPathBlock) oldQP.getElements().get(index); 
}else{ 
    //...no occurence, so make new ElementPathBlock to add 
    epb = new ElementPathBlock(); 
} 
//add Triple(s) to epb, not to oldQP 
epb.addTriple(t); 
//re-add (or add for first time) ElementPathBlock to the ArrayList of Elements 
if(index > -1){ 
    oldQP.getElements().set(index, epb); 
}else{ 
    oldQP.getElements().add(epb); 
} 

//same as before 
nq.setQueryPattern(oldQP); 
nq.setQuerySelectType(); 
nq.setQueryResultStar(false); 
nq.addResultVar("s"); 

看着在oldQP现在,上面之后,我们看到它的格式正确,且该期限是否正确放置:

{?s ?p ?o. 
?s2 ?p2 ?s. 
}