由于键入文字 (xsd:string) 从 Jena 查询 SPARQL 而无法获得结果;
Can't get results due to typed literal (xsd:string) querying SPARQL from Jena;
我已经加载了我的 Virtuoso 服务器 运行 ontology,下面的查询通过将它粘贴到网络上 sparql 端点的文本字段来工作(ronto,我的前缀ontology 由于安全原因我跳过了(抱歉),但我确定它的定义正确,因为查询有效但 returns 空列表这是一个问题):
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
select distinct (str(?p) as ?theme) where {?s ronto:isin "id-XXXX"^^xsd:string; ronto:mainThemes ?p}
以下不起作用(returns空列表);注意跳过的
xsd:string
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
select distinct (str(?p) as ?theme) where {?s ronto:isin "id-XXXX"; ronto:mainThemes ?p}
因此,问题:我无法从 Java 获得相同的结果,Jena deps 是:
<dependency>
<groupId>org.apache.jena</groupId>
<artifactId>jena-arq</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.jena</groupId>
<artifactId>jena-core</artifactId>
<version>3.0.1</version>
</dependency>
所以,玩具代码:
public static void main(String[] args) {
String isin = "id-XXXX";
final ParameterizedSparqlString qs = new ParameterizedSparqlString(
"select ?p where {?s ronto:isin ?isin^^xsd:string; ronto:mainThemes ?p.}");
qs.setBaseUri(base);
qs.setNsPrefix("owl", "http://www.w3.org/2002/07/owl#");
qs.setNsPrefix("xsd", "http://www.w3.org/2001/XMLSchema#");
qs.setNsPrefix("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
qs.setNsPrefix("rdfs", "http://www.w3.org/2000/01/rdf-schema#");
qs.setLiteral("isin", isin);
System.out.println("Running as a query " +qs.asQuery());
try (QueryExecution exec = QueryExecutionFactory.sparqlService(publicSparqlEndpoint, qs.asQuery())) {
final ResultSet resultSet = exec.execSelect();
System.out.println(exec.getQuery());
ResultSetFormatter.out(resultSet);
}
System.out.println("Running as a string " + qs.toString());
try (QueryExecution exec = QueryExecutionFactory.sparqlService(publicSparqlEndpoint, qs.toString())) {
final ResultSet resultSet = exec.execSelect();
System.out.println(exec.getQuery());
ResultSetFormatter.out(resultSet);
}
输出为
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
SELECT ?p
WHERE
{ ?s ronto:isin "id-XXXX" ;
ronto:mainThemes ?p
}
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
SELECT ?p
WHERE
{ ?s ronto:isin "id-XXXX" ;
ronto:mainThemes ?p
}
-----
| p |
=====
-----
Running as a string
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
select ?p where {?s ronto:isin "id-XXXX"^^xsd:string; ronto:mainThemes ?p.}
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
SELECT ?p
WHERE
{ ?s ronto:isin "id-XXXX" ;
ronto:mainThemes ?p
}
-----
| p |
=====
-----
其中 p-boxes 是端点的空列表结果;
我测试了不基于类型文字的更简单的查询(xsd:此处为字符串),它们给了我非空结果;
所以,很容易发现 exec 对象有 skipped xsd:string 的查询,我猜这是一个导致空列表的问题,但为什么它会以这种方式工作,什么是解决方法的干净方法?
解决方案 感谢@AndyS(请注意两个更改:查询中的 FILTER 和 QueryEngineHTTP):
public static void main(String[] args) {
String isin = "id-XXXX";
final ParameterizedSparqlString qs = new ParameterizedSparqlString(
"select ?p where {?s ronto:isin ?X; ronto:mainThemes ?p. FILTER (?X= ?isin^^xsd:string)}");
qs.setBaseUri(base);
qs.setNsPrefix("owl", "http://www.w3.org/2002/07/owl#");
qs.setNsPrefix("xsd", "http://www.w3.org/2001/XMLSchema#");
qs.setNsPrefix("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
qs.setNsPrefix("rdfs", "http://www.w3.org/2000/01/rdf-schema#");
qs.setNsPrefix("ronto", "....");
qs.setLiteral("isin", isin);
System.out.println("Running as a string " + qs.toString());
try (QueryEngineHTTP exec = new QueryEngineHTTP(publicSparqlEndpoint, qs.toString())) {
final ResultSet resultSet = exec.execSelect();
System.out.println(exec.getQuery());
ResultSetFormatter.out(resultSet);
}
}
在 RDF 1.1 中,不带 xsd:string
的字符串和带 xsd:string
的字符串是相同的 RDF 术语。写不写^^xsd:string
都没关系
ARQ 打印不带 ^^xsd:string
的查询,这用于远程 SPARQL 调用。
Virtuoso 实例似乎与 RDF 1.1 不兼容。
您可以在查询中尝试 value-expression:
{ ?s ronto:isin ?X;
ronto:mainThemes ?p.
FILTER ( ?X = "id-XXXX"^^xsd:string)
}
适用于 RDF 1.0 和 RDF 1.1 以及混合系统。
或者,直接使用 QueryEngineHTTP
,而不是 QueryExecutionFactory
。这允许应用程序传入一个字符串作为发送到远程端点的查询,而无需解析或检查。
我已经加载了我的 Virtuoso 服务器 运行 ontology,下面的查询通过将它粘贴到网络上 sparql 端点的文本字段来工作(ronto,我的前缀ontology 由于安全原因我跳过了(抱歉),但我确定它的定义正确,因为查询有效但 returns 空列表这是一个问题):
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
select distinct (str(?p) as ?theme) where {?s ronto:isin "id-XXXX"^^xsd:string; ronto:mainThemes ?p}
以下不起作用(returns空列表);注意跳过的
xsd:string
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
select distinct (str(?p) as ?theme) where {?s ronto:isin "id-XXXX"; ronto:mainThemes ?p}
因此,问题:我无法从 Java 获得相同的结果,Jena deps 是:
<dependency>
<groupId>org.apache.jena</groupId>
<artifactId>jena-arq</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.jena</groupId>
<artifactId>jena-core</artifactId>
<version>3.0.1</version>
</dependency>
所以,玩具代码:
public static void main(String[] args) {
String isin = "id-XXXX";
final ParameterizedSparqlString qs = new ParameterizedSparqlString(
"select ?p where {?s ronto:isin ?isin^^xsd:string; ronto:mainThemes ?p.}");
qs.setBaseUri(base);
qs.setNsPrefix("owl", "http://www.w3.org/2002/07/owl#");
qs.setNsPrefix("xsd", "http://www.w3.org/2001/XMLSchema#");
qs.setNsPrefix("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
qs.setNsPrefix("rdfs", "http://www.w3.org/2000/01/rdf-schema#");
qs.setLiteral("isin", isin);
System.out.println("Running as a query " +qs.asQuery());
try (QueryExecution exec = QueryExecutionFactory.sparqlService(publicSparqlEndpoint, qs.asQuery())) {
final ResultSet resultSet = exec.execSelect();
System.out.println(exec.getQuery());
ResultSetFormatter.out(resultSet);
}
System.out.println("Running as a string " + qs.toString());
try (QueryExecution exec = QueryExecutionFactory.sparqlService(publicSparqlEndpoint, qs.toString())) {
final ResultSet resultSet = exec.execSelect();
System.out.println(exec.getQuery());
ResultSetFormatter.out(resultSet);
}
输出为
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
SELECT ?p
WHERE
{ ?s ronto:isin "id-XXXX" ;
ronto:mainThemes ?p
}
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
SELECT ?p
WHERE
{ ?s ronto:isin "id-XXXX" ;
ronto:mainThemes ?p
}
-----
| p |
=====
-----
Running as a string
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
select ?p where {?s ronto:isin "id-XXXX"^^xsd:string; ronto:mainThemes ?p.}
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
SELECT ?p
WHERE
{ ?s ronto:isin "id-XXXX" ;
ronto:mainThemes ?p
}
-----
| p |
=====
-----
其中 p-boxes 是端点的空列表结果;
我测试了不基于类型文字的更简单的查询(xsd:此处为字符串),它们给了我非空结果;
所以,很容易发现 exec 对象有 skipped xsd:string 的查询,我猜这是一个导致空列表的问题,但为什么它会以这种方式工作,什么是解决方法的干净方法?
解决方案 感谢@AndyS(请注意两个更改:查询中的 FILTER 和 QueryEngineHTTP):
public static void main(String[] args) {
String isin = "id-XXXX";
final ParameterizedSparqlString qs = new ParameterizedSparqlString(
"select ?p where {?s ronto:isin ?X; ronto:mainThemes ?p. FILTER (?X= ?isin^^xsd:string)}");
qs.setBaseUri(base);
qs.setNsPrefix("owl", "http://www.w3.org/2002/07/owl#");
qs.setNsPrefix("xsd", "http://www.w3.org/2001/XMLSchema#");
qs.setNsPrefix("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
qs.setNsPrefix("rdfs", "http://www.w3.org/2000/01/rdf-schema#");
qs.setNsPrefix("ronto", "....");
qs.setLiteral("isin", isin);
System.out.println("Running as a string " + qs.toString());
try (QueryEngineHTTP exec = new QueryEngineHTTP(publicSparqlEndpoint, qs.toString())) {
final ResultSet resultSet = exec.execSelect();
System.out.println(exec.getQuery());
ResultSetFormatter.out(resultSet);
}
}
在 RDF 1.1 中,不带 xsd:string
的字符串和带 xsd:string
的字符串是相同的 RDF 术语。写不写^^xsd:string
都没关系
ARQ 打印不带 ^^xsd:string
的查询,这用于远程 SPARQL 调用。
Virtuoso 实例似乎与 RDF 1.1 不兼容。
您可以在查询中尝试 value-expression:
{ ?s ronto:isin ?X;
ronto:mainThemes ?p.
FILTER ( ?X = "id-XXXX"^^xsd:string)
}
适用于 RDF 1.0 和 RDF 1.1 以及混合系统。
或者,直接使用 QueryEngineHTTP
,而不是 QueryExecutionFactory
。这允许应用程序传入一个字符串作为发送到远程端点的查询,而无需解析或检查。