桂林山水甲天下

Jacquette的技术生活

品尝SPARQL系列之二 在.NET中跨平台调用Joseki的SPARQL Web Services

在Joseki中,已经开发了SPARQL查询的Web Services,在Joseki3\src-soap\org\joseki\soap目录中。现在要说明的是如何在.NET平台上调用该Web Services。

首先,如系列一所写的那样,先在Java平台上调用成功。

跨平台调用的关键在于找到该Web Services的接口文件(WSDL)以及复杂类型的定义xsd文件,然后利用wsdl工具生成客户端代理类。由于SPARQL已经有相关的W3C建议文档,而Joseki是完全按照文档实现该协议的,下面的网址是SPARQL的HTTP绑定和SOAP绑定的协议文档:
http://www.w3.org/TR/rdf-sparql-protocol/ 

关于WSDL的版本问题

在这个W3C文档中,可以找到sparql ws接口定义文件,其网址是http://www.w3.org/TR/rdf-sparql-protocol/sparql-protocol-query.wsdl是遵循http://www.w3.org/2006/01/wsdl所制定的WSDL2.0的,这个版本目前不被Visual Studio 2005自带的wsdl.exe工具支持,因此,需要将其修改成旧版本的wsdl。首先是缺省命名空间的改动,VS2005中缺省命名空间应该是:http://schemas.xmlsoap.org/wsdl/,否则wsdl.exe会报错的。另外,wsdl1.0中PortType在wsdl2.0中是interface,并且wsdl1.0中message的定义是在PortType前面的,总之,拿VS2005生成的任何一个wsdl文件和这个新版本的sparql-protocol-query.wsdl比较一下结构,改动还是不难的。

生成客户端代理类

在这个wsdl文件的<types>…</types>部分,是关于message中用到的复杂类型的Schema定义,当类型定义比较多时,可以将其分别放入不同的xsd文件中,而在wsdl中采用<import> 标签:
<types>
   <xs:import namespace="http://www.w3.org/2005/09/sparql-protocol-types/#"
      schemaLocation="sparql-protocol-types.xsd"/>
</types> 

上面说的这个W3C文档还给出了http://www.w3.org/TR/rdf-sparql-protocol/sparql-protocol-types.xsd,里面是关于 sparql-request, sparql-result和定义。在这个xsd中又需要导入关于sparql result中几个元素的定义,下面的网址介绍了SPARQL的查询结果XML Format:http://www.w3.org/TR/rdf-sparql-XMLres/
里面找到http://www.w3.org/TR/rdf-sparql-XMLres/result2.xsd

因此,需要紧接着在<xs:schema targetNamespace="http://www.w3.org/2005/09/sparql-protocol-types/#"。。。。>之后加入
<xs:import namespace="http://www.w3.org/1999/02/22-rdf-syntax-ns#" schemaLocation="rdf.xsd"/>  
<xs:import namespace="http://www.w3.org/2005/sparql-results#" schemaLocation="result2.xsd"/> 
而result2.xsd中,又需要加入:
<xs:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="xml.xsd"/> 

现在,将sparql-protocol-query.wsdl和sparql-protocol-types.xsd/result2.xsd/xml.xsd/rdf.xsd放在同一个目录下,从Visual Studio Tools目录打开Visual Studio 2005 命令行工具,转到这几个文件所在目录键入如下命令:
wsdl sparql-protocol-query.wsdl sparql-protocol-types.xsd result2.xsd xml.xsd rdf.xsd
即生成出在.net平台下调用sparql WS的客户端代理类。

跨平台调用及其返回结果

在.net平台下用c#编写简单的程序调用sparql WS,查询的RDF数据源使用josek3/Data目录下的例子books.n3:

@prefix dc:        <http://purl.org/dc/elements/1.1/> .
@prefix vcard:     <http://www.w3.org/2001/vcard-rdf/3.0#> .
@prefix ns:        <http://example.org/ns#> .
@prefix :          <http://example.org/book/> . 

:book1
    dc:title    "Harry Potter and the Philosopher's Stone" ;
    dc:creator  "J.K. Rowling" ;
    .  
:book2
    dc:title    "Harry Potter and the Chamber of Secrets" ;
    dc:creator  _:a .  
:book3
    dc:title    "Harry Potter and the Prisoner Of Azkaban" ;
    dc:creator  _:a .  
:book4
    dc:title    "Harry Potter and the Goblet of Fire" . 
:book5
    dc:title    "Harry Potter and the Order of the Phoenix".  
:book6
    dc:title    "Harry Potter and the Half-Blood Prince".    
_:a
    vcard:FN "J.K. Rowling" ;
    vcard:N
        [ vcard:Family "Rowling" ;
          vcard:Given "Joanna"
        ].

SPARQL语句SELECT ?z {?x ?y ?z . FILTER regex(?z, 'Harry')},将返回所有value的前缀为harry的三元组。

在java平台下打开org.apache.axis.utils.tcpmon可监视soap包的内容,注意tcpmon监听端口的设置和C#客户端设置的调用Web服务地址端口应该一致,而target port是Web服务的真实调用地址端口。这样,soap请求就先发送到监听端口,然后tcpmon截获该消息,同时将请求发送给target port,这样就可以既截获请求,又调用Web服务。

例如,若Joseki3中sparql services的地址是:
http://localhost:2525/axis/services/sparql-query
则设置Listener的target hostname&port是127.0.0.1:2525,
若设置Listen port是1234,则应该将wsdl.exe生成的客户端代理类中指定的web服务URL修改为
http://localhost:1234/axis/services/sparql-query

 

C#客户端调用Web服务
String queryStr = "SELECT ?z{?x ?y ?z . FILTER regex(?z, 'Harry')}\n";
SparqlQueryService service = new SparqlQueryService();
sparql s = (sparql)service.query(queryStr, null, null); 

其中sparql、results、item等是对应前面介绍的几个xsd中定义的复杂类型,要理解这几个类的数据结构,还是要回到sparql协议文档,看看SPARQL查询结果的XML格式:
<sparql xmlns="http://www.w3.org/2005/sparql-results#">
  <head>
    <variable name="name"/>
  </head>
  <results ordered="false" distinct="false">
    <result>
      <binding name="name">
        <literal datatype="http://www.w3.org/2001/XMLSchema#string">
        </literal>
      </binding>
    </result>
   <!-- more results -->
   </results>
</sparql>

如同SQL的查询结果一样,SPARQL查询结果也是“行”“列”来构成的,这种格式通过使用XSLT就可以简单地转换为HTML格式的网页呈现出来。

<head>标签中的内容是“列”(variable)的名字;而<results>标签包括数个<result>,每个result是一“行”,每“行”中内容是多个<binding name="name">,binding的名字属性对应列的名字,每个元素的内容可以是literal, bnode和uri。

C#调用客户端代理类返回的sparql对象并不直观,因此,如同Joseki3中使用的com.hp.hpl.jena.query.Query命名空间中的ResultSet(继承自Iterator迭代类)一样,在C#中可以将其对结果的处理代码移植过来使用,调用WS而返回类似的ResultSet。

好,示例程序已经说明,现在无论是在java平台还是.net平台,sparql调用的路途已经基本畅通了。下面,系列三将举几个更为实际一些的例子,说明一下SPARQL的用途。

posted on 2006-10-21 21:02  Jacquette.wang  阅读(2031)  评论(0编辑  收藏  举报

导航