Java 不存在的“.”在添加三元组Jena ElementGroup后导致分析错误
我正在尝试基于给定查询构造新查询-旧查询-我无法更改此设置 假设给我一个简单有效的SPARQL查询,选择?s WHERE{s?p?o}。假设我为上述查询创建了一个jena查询对象,并将查询模式作为java中的ElementGroup获取,如下所示:Java 不存在的“.”在添加三元组Jena ElementGroup后导致分析错误,java,sparql,jena,Java,Sparql,Jena,我正在尝试基于给定查询构造新查询-旧查询-我无法更改此设置 假设给我一个简单有效的SPARQL查询,选择?s WHERE{s?p?o}。假设我为上述查询创建了一个jena查询对象,并将查询模式作为java中的ElementGroup获取,如下所示: Query q = QueryFactory.create("SELECT ?s WHERE{ ?s ?p ?o }, Syntax.syntaxSPARQL_11); ElementGroup oldQP = (ElementGroup)q.get
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。那么,如何避免这个问题呢?如果所有三元组都有结束期,则不会出现此问题,但我似乎找不到任何方法来实现此功能
谢谢 我不确定我是否完全理解你的问题 第二个查询来自哪里?您是否在新查询对象上调用toString,在这种情况下,这可能是打印查询的内部逻辑中的错误
另外,您使用的是什么版本的ARQ?因此,我似乎找到了一个解决方法。 在调试并更仔细地查看由该行创建的ElementGroup对象之后
ElementGroup oldQP = (ElementGroup)q.getQueryPattern();
我注意到它显示了通过方法ElementGroup.getElements检索的元素对象的ArrayList。在我试图通过ElementGroup.addTriplePattern添加三元组之前,列表中唯一的一件事。。。方法是ElementPathBlock类型的对象。好的,酷
接下来,我尝试通过上述方法添加三元组,如下所示:
Triple t = Triple.create(...);
oldQP.addTriplePattern(t);
我注意到这将向ElementGroup的元素列表添加一个新的ElementTriplesBlock。看来这就是罪魁祸首。因此,我的解决方案是获取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");
下面的代码如您所述创建查询、复制查询、添加三重模式、打印查询并运行这两个查询。您是对的,查询的打印表单缺少。通常会有人在场的地方。然而,作为RobV,打印的奇怪之处对查询结果没有任何影响。如果你在实际案例中得到不同的结果,你能强调一下与此不同的地方吗
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> |
--------------
System.out.printlnnq.serialize-是的,打印新的查询对象。但进行一些调试后,ElementGroup本身的oldQP看起来是这样的,所以我不认为它是专门打印的。很抱歉给你带来了困惑。本质上,问题似乎是,当您将三元组添加到一个类似{s?p?o}的查询模式时,您会得到一个类似{s?p?o?s2?p2?s?s3?p3?s2}等的查询模式,即s.t。添加的第一个三元组和下一个三元组之间没有使用正确的语法a.'字符分隔。我相信我正在使用arq-2.8.5-patched-2.jar。好吧,你的问题很可能是它是一个非常旧的arq版本,2.8.5是从2010年7月开始的,当前的2.10.0版本是在2013年3月发布的。如果你有能力,你真的应该升级你的依赖关系。再次阅读你的问题,为什么你要把它打印成字符串,然后重新解析?不可能直接执行您创建的新查询对象,从而完全避免此问题吗?抱歉。我不会打印成字符串并再次解析它。我只是执行我直接创建的新查询对象;我上面打印出来的查询只是为了总结/概述这个问题。本质上,当您有一个类似以下内容的QueryPattern元素时:{s?p?o}例如通过Query.getQueryPattern方法获得,并且您尝试通过ElementGroup.addTriplePattern向其添加三元组。。。方法,得到一个元素组,看起来像{s?p?p?s2?p2?s…},注意不存在的句点。这会在创建新查询对象时引发问题。句点只是序列化语法,在代码中没有内部表示形式,如果这会导致问题,那么代码中的某些内容一定会在某个时候将查询转换为字符串。不管怎样,我的假设是,这是您正在使用的将近3年的ARQ版本中的一个bug,重申一下,请升级到一个更新的版本,看看您是否仍然可以重现问题re:Missing。旧bug-至少在开发代码库中修复了。@AndyS RobV的回答表明它也是已知的和旧的。我只是想在这里得到一个完整的工作示例,以供其他人参考;现在他们可以看到他们应该能做什么了。
== 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> |
--------------