【问题标题】:Can't get results due to typed literal (xsd:string) querying SPARQL from Jena;由于输入文字 (xsd:string) 从 Jena 查询 SPARQL,无法获得结果;
【发布时间】:2016-01-03 23:39:56
【问题描述】:

我的 Virtuoso 服务器使用加载的本体运行,以下查询通过将其粘贴到网络上 sparql 端点的文本字段来工作(ronto,由于安全原因,我跳过了我的本体的前缀(抱歉),但我确定它的定义正确,因为查询有效但返回空列表,这是一个问题):

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}

以下不起作用(返回空列表);注意跳过的

xsd:字符串

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 部门是:

        <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-box 是来自端点的空列表结果;

我测试了不基于类型文字(此处为 xsd:string)的更简单查询,它们给了我非空结果;

因此,很容易发现 exec 对象具有跳过 xsd:string 的查询,我猜这是导致得到空列表的问题,但为什么它会以这种方式工作并且什么是解决方法的干净方法?

解决方案感谢@AndyS(注意两个变化:查询中的过滤器和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);
    }
}

【问题讨论】:

    标签: java xsd sparql jena string-literals


    【解决方案1】:

    在 RDF 1.1 中,不带 xsd:string 的字符串和带 xsd:string 的字符串是同一个 RDF 术语。写不写^^xsd:string没关系。

    ARQ 打印没有^^xsd:string 的查询,这用于远程 SPARQL 调用。

    看起来 Virtuoso 实例与 RDF 1.1 不兼容。

    您可以在查询中尝试值表达式:

    { ?s ronto:isin ?X;
         ronto:mainThemes ?p.
      FILTER ( ?X = "id-XXXX"^^xsd:string)
    }
    

    适用于 RDF 1.0 和 RDF 1.1 以及混合系统。

    或者,直接使用QueryEngineHTTP,而不是QueryExecutionFactory。这允许应用程序传入一个字符串作为发送到远程端点的查询,而无需解析或检查。

    【讨论】:

    • 谢谢,它仅在我应用 FILTER 并使用 QueryEngineHTTP 将查询作为字符串传递时才有效。 @AndyS,你拯救了我的一天。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-04
    • 1970-01-01
    相关资源
    最近更新 更多