【问题标题】:How to add Triples to a Jena Query dynamically using ElementWalker?如何使用 ElementWalker 动态地将三元组添加到 Jena 查询?
【发布时间】:2013-07-24 17:17:43
【问题描述】:

假设我有一些耶拿查询对象:

String query = "SELECT * WHERE{ ?s <some_uri> ?o ...etc. }";
Query q = QueryFactory.create(query, Syntax.syntaxARQ);

我想使用 ElementWalker 并将三元组添加到查询中,如下所示:

给定一个查询

SELECT * WHERE {
    ?s ?p ?o;
       ?p2 ?o2.
    ?s2 ?p3 ?o3.
}

我希望添加一个三重 s.t.查询看起来像:

    SELECT * WHERE {
    ?s ?p ?o;
       ?p2 ?o2.
 -->?s <some_url> "value". //added
    ?s2 ?p3 ?o3.
}

我知道有一些方法可以添加到顶层 (Jena Tutorial),但我想在使用 ElementWalker 遍历它们时以某种方式添加三元组:

ElementWalker.walk(query.getQueryPattern(), new ElementVisitorBase(){

        public void visit(ElementPathBlock el) {

            // when it's a block of triples, add in some triple
            ElementPathBlock elCopy = new ElementPathBlock();
            Iterator<TriplePath> triples = el.patternElts();
            int index = 0;
            int numAdded = 0;
            while (triples.hasNext()) {
                TriplePath t = triples.next();
                if(t.getSubject().equals(/*something*/)){
                    //add triple here, something like:
                    elCopy.addTriple(index+numAdded, /*someTriple*/);
                    numAdded++;
                }
                index++;
            }
            el = elCopy;
        }

        public void visit(ElementSubQuery el) {

            // get the subquery and walk it
            ElementGroup subQP = (ElementGroup) el.getQuery().getQueryPattern();
            ElementWalker.walk(subQP, this);
        }

        public void visit(ElementOptional el) {

            // get optional elements and walk them
            Element optionalQP = el.getOptionalElement();
            ElementWalker.walk(optionalQP, this);
        }
    });

上述代码的问题在于它成功地将三元组添加到 ElementPathBlock (el),但这种更改不会持续到查询本身。我希望在访问查询内部的这个特定 ElementPathBlock 时成功修改查询。

任何帮助表示赞赏。

【问题讨论】:

    标签: java sparql semantic-web jena


    【解决方案1】:

    此代码使用walker 在任何主题为?d 的三元组之后添加?d ?d ?d。由于主题为 ?d 的查询中有多个三元组,因此会插入多个 ?d ?d ?d 实例,并保留更改。

    import java.util.ListIterator;
    
    import com.hp.hpl.jena.graph.Triple;
    import com.hp.hpl.jena.query.Query;
    import com.hp.hpl.jena.query.QueryFactory;
    import com.hp.hpl.jena.sparql.core.TriplePath;
    import com.hp.hpl.jena.sparql.core.Var;
    import com.hp.hpl.jena.sparql.syntax.ElementPathBlock;
    import com.hp.hpl.jena.sparql.syntax.ElementVisitorBase;
    import com.hp.hpl.jena.sparql.syntax.ElementWalker;
    
    public class ElementWalkerExample {
        public static void main(String[] args) {
            final String queryString  = "" +
                "SELECT * WHERE {\n" +
                " ?a ?b ?c1 ;\n" +
                "    ?b ?c2 .\n" +
                " ?d ?e ?f .\n" +
                " ?g ?h ?i .\n" +
                "{ ?p ?q ?r .\n" +
                "  ?d ?e2 ?f2 . }\n" +
                "}";
            final Query query = QueryFactory.create( queryString );
            System.out.println( "== before ==\n"+query );
            ElementWalker.walk( query.getQueryPattern(), 
                    new ElementVisitorBase() {
                        @Override
                        public void visit(ElementPathBlock el) {
                            ListIterator<TriplePath> it = el.getPattern().iterator();
                            while ( it.hasNext() ) {
                                final TriplePath tp = it.next();
                                final Var d = Var.alloc( "d" );
                                if ( tp.getSubject().equals( d )) {
                                    it.add( new TriplePath( new Triple( d, d, d )));
                                }
                            }
                        }
            });
            System.out.println( "== after ==\n"+query );
        }
    }
    

    输出是:

    == before ==
    SELECT  *
    WHERE
      { ?a ?b ?c1 .
        ?a ?b ?c2 .
        ?d ?e ?f .
        ?g ?h ?i
        { ?p ?q ?r .
          ?d ?e2 ?f2
        }
      }
    
    == after ==
    SELECT  *
    WHERE
      { ?a ?b ?c1 .
        ?a ?b ?c2 .
        ?d ?e ?f .
        ?d ?d ?d .
        ?g ?h ?i
        { ?p ?q ?r .
          ?d ?e2 ?f2 .
          ?d ?d ?d
        }
      }
    

    【讨论】:

    • 另外,对于其他阅读本文的人,还有更多关于如何在this answer(不是我的)中使用 ElementWalkers 的示例来解决DirectCtrl 的另一个问题。
    • 所以这里的主要思想是在ListIterator&lt;TriplePath&gt; it = el.getPattern().iterator();这一行。通过使用它而不是Iterator&lt;TriplePath&gt; it = el.patternElts();,我可以使用提供的it.add(...) 来添加三元组。效果很好,感谢您的帮助。
    • @DirectCtrl 对,ListIterator 可以让你在中间添加。如果这对您有用,请随时 accept 让其他用户知道它有效!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多