简体   繁体   中英

Interpolate a string into a SPARQL query with Jena

I want to create a SPARQL queries from Java (particularly, Jena and ARQ). I want to make it possible for a user who may not know anything about SPARQL to make a query by just writing (eg, in a console from Eclipse) the word he wants to search for. The following code gives an example of what I'm looking for. How can I interpolate the string word into the query?

String word="someThingToFind"; // a variable entered by the user who want to request my data
String queryString =
"Select ?a ?b"+
    " Where { ...."+
    " Filter (regex(?a = ".concat(word)+ "))"+// word is the String variable 
" }";

Query query = QueryFactory.create(queryString, Syntax.syntaxARQ);   
QueryExecution qe = QueryExecutionFactory.create(query, model);
ResultSet results = qe.execSelect();
ResultSetFormatter.out(System.out, results, query);
qe.close();

This line in your code

Filter (regex(?a = ".concat(word)+ "))"+// word is the String variable

will produce SPARQL text like (assuming that word is banana):

Filter (regex(?a = banana))

That's not how regex is used in SPARQL. When you're trying to parameterize queries, it's a good idea to make sure that you've got a working form to begin with, and then you can start making parts of it parameterized. Sure enough, if you take a stripped down version of your query:

select * where { filter(regex(?a = "banana")) }

and paste it into the sparql.org's validator , you'll see that it's a syntax error. However, the documentation for regex has some examples. regex takes two required arguments, and one optional argument:

  1. a string (the text)
  2. another string (the pattern)
  3. (optional) a string containing flags (eg, "i" , for case insensitive matching)

To use regex , you'd need to do something like:

"filter(regex(?a, \"" + word + "\"))"

so that you can get

filter(regex(?a,"banana"))

in the query. Of course, this opens you up to a classic injection problems, since you've got a problem if word contains " . This is why you should use a ParameterizedSparqlString ; you can have

filter(regex(?a,?word))

and then just replace ?word with the value of word , and all the escaping will be handled correctly.

There are two options to include parameters in query strings. You don't need to use the filter unless you want to use more advanced functions, like patterns. When selecting triples, you can just use the user provided value as the triple's object:

... WHERE {
    ?subject pred:somePred "value"
}

To include the value in the query it is best to use a QuerySolutionMap to bind a SPARQL parameter to some value, as documented on http://jena.apache.org/documentation/query/parameterized-sparql-strings.html Otherwise, escape all special characters in the user provided string (" most important) and use Java string concatenation to include the value. The above example would become

... WHERE {
    ?subject pred:somePred ?value
}

Later you would bind the name "value" to the user provided value.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM