zoukankan      html  css  js  c++  java
  • Javascript实现关联数据(Linked Data)查询

    前言

    自由百科全书不仅仅应当可以自由编写,而更应该可以自由获得。

    DBpedia对Wikipedia的数据变成Linked Data形式,使得机器也能读懂并自由获得这些数据。

    本文的主要目的是利用Javascript从DBpedia中获取我们想要的数据。

    对Linked Data不太了解的请参考:关联数据入门——RDF

    SPARQL

    Trying to use the Semantic Web without SPARQL is like trying to use a relational database without SQL.

    —— Tim Berners-Lee

    SPARQL是Semantic Web(语义网)的SQL,用于数据查询的语言。

    SPARQL Endpoint

    SPARQL查询终端,是一种HTTP绑定协议,用于通过HTTP进行SPARQL查询,并返回相应数据。

    DBpedia的SPARQL Endpoint地址是:http://dbpedia.org/sparql

    大家可以通过浏览器打开这个页面,进行SPARQL查询(最好FQ,没FQ查询经常失败,不太明白为什么= =)。 

    不过这种查询最终返回结果是HTML页面,并不是我们想要的,我们可以通过设置Request Header的Accept属性来指定返回数据类型。

    例如如果指定为:text/xml,那么返回的便是RDF格式数据。

    那么我们如何输入SPARQL查询代码呢?

    只需通过get或者post方法用参数query,将代码传过去。例如:

    如果想查询:select distinct ?Concept where {[] a ?Concept} LIMIT 100

    则可利用该链接得到数据:

    http://dbpedia.org/sparql?query=select%20distinct%20?Concept%20where%20{[]%20a%20?Concept}%20LIMIT%20100

    其中空格被转成%20。

    实现细节

    • 跨域

    我们可以通过AJAX实现这一功能,但是AJAX在部分浏览器中无法跨域,然而很显然我们想要的Linked Data几乎都是跨域的。

    实际上,在一些较老版本的浏览器,我们没有不改变其数据形式的方法在前端进行动态跨域异步读取。

    不过我们可以通过服务器代理的方法来解决跨域问题。

    • GET or POST 

    使用GET还POST呢?

    这个可能出于很多方面考虑,但是考虑到GET可能被缓存,所以我们使用POST来避免数据被缓存。

    • 以什么形式返回数据

    前面我们说到用text/xml可以返回RDF数据,但是RDF在Javascript中并不好处理,所以我们使用json方式返回,也就是需要将Accept设置成application/sparql-results+json。

    实现

    接口参考Python的SPARQL Wrapper

    (function(root, factory) {
        if(typeof define === "function"){
            define("SPARQLWrapper", factory);    // AMD || CMD
        }else{
            root.SPARQLWrapper = factory();    // <script>
        }
    }(this, function(){
    'use strict'
    
    function SPARQLWrapper(endpoint){
        this.endpoint = endpoint;
        this.queryPart = "";
        this.type = "json";
    }
    SPARQLWrapper.prototype = {
        constructor: SPARQLWrapper,
        setQuery: function(query){
            this.queryPart = "query=" + encodeURI(query);
        },
        setType: function(type){
            this.type = type.toLowerCase();
        },
        query: function(type, callback){
            callback = callback === undefined ? type : this.setType(type) || callback;
            
            var xhr = new XMLHttpRequest();
            xhr.open('POST', this.endpoint, true);
            xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
            switch(this.type){
                case "json":
                    type = "application/sparql-results+json";
                    break;
                case "xml":
                    type = "text/xml";
                    break;
                case "html":
                    type = "text/html";
                    break;
                default:
                    type = "application/sparql-results+json";
                    break;
            }
            xhr.setRequestHeader("Accept", type);
            xhr.onreadystatechange = function(){
                if(xhr.readyState == 4){
                    var sta = xhr.status;
                    if(sta == 200 || sta == 304){
                        callback(xhr.responseText);
                    }else{
                        console && console.error("Sparql query error: " + xhr.status + " " + xhr.responseText);
                    }
            
                    window.setTimeout(function(){
                        xhr.onreadystatechange= new Function();
                        xhr = null;
                    },0);
                }
            }
            
            xhr.send(this.queryPart);
        }
    }
    
    
    return SPARQLWrapper;
    
    }));

    使用方法,例如需要查询:

    select distinct ?Concept where {[] a ?Concept} LIMIT 100

    则该页面为:

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml"> 
    <head> 
    <meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> 
    <script src="SPARQLWrapper.js" type="text/javascript"></script>
    </head>
    <body> 
    <script>
    
    var sparql = new SPARQLWrapper("http://dbpedia.org/sparql");
    sparql.setQuery('select distinct ?Concept where {[] a ?Concept} LIMIT 100');
    sparql.query(function(json){
        console.log(json);
    });
    </script>
    </body> 
    </html> 

    小例子

    http://pan.baidu.com/share/link?shareid=293219&uk=855675565

    修订记录

    • 修正关于跨域的错误 2003.2.21
  • 相关阅读:
    okhttp之源码学习1
    Retrofit2之源码解析2
    Retrofit2之源码解析1
    retrofit之笔记内容
    retrofit之基本笔记
    retrofit之基本内容
    rxjava-源码分析
    rxjava-基本内容解析
    rxjava_几类转换
    java几种常见的编码
  • 原文地址:https://www.cnblogs.com/justany/p/2920151.html
Copyright © 2011-2022 走看看