不存在的 '。'添加三元组Jena ElementGroup后导致解析错误

时间:2013-03-22 18:15:28

标签: java sparql jena

我正在尝试根据给定的查询构建一个新查询(旧查询 - 我无法更改此信息)。

假设我获得了一个简单有效的SPARQL查询SELECT ?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.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。那么,如何避免这个问题呢?如果所有三元组都有结束时间段,则不会发生此问题,但我似乎找不到任何方法来使其工作。

谢谢!

3 个答案:

答案 0 :(得分:1)

我不确定我是否完全按照你的问题

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

您还在使用什么版本的ARQ?

答案 1 :(得分:1)

所以我似乎找到了一个解决方法/解决方案。 经过调试并仔细查看由行

创建的ElementGroup对象
ElementGroup oldQP = (ElementGroup)q.getQueryPattern();

我注意到它运行了Element对象的ArrayList(通过方法ElementGroup.getElements()检索)。在我尝试添加三元组(通过ElementGroup.addTriplePattern(...)方法)之前,此列表中唯一的内容是类型ElementPathBlock的对象。好的,很酷。

接下来,我尝试通过上面的方法添加三元组,如下所示:

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

我注意到这会在ElementGroup的Elements列表中添加一个新的ElementTriplesBlock。这似乎是罪魁祸首。所以,我的解决方案是获取最后一次出现的ElementPathBlock,并将三元组添加到该对象而不是将它们添加到ElementGroup(从而避免将新的ElementTriplesBlock添加到ArrayList): / p>

//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.
}

答案 2 :(得分: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> |
--------------