品尝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) 编辑 收藏 举报