Objective-CからSPARQLを利用するには
SPARQLは、エンドポイントと呼ばれるURIにGETリクエストでSPARQLクエリを投げると、json、xmlなど(指定可能)がレスポンスで返ってきます。
例えば、大津市内の観光名所のデータ一覧を取得する場合は
prefix geo: <http://www.w3.org/2003/01/geo/wgs84_pos# ≷
prefix schema: <http://schema.org/ ≷
prefix place: <http://fp.yafjp.org/terms/place# ≷
select * where {
?uri geo:lat ?lat;
geo:long ?long;
rdfs:label ?label;
schema:address ?address;
schema:description ?description;
place:access ?access;
schema:url ?homepage.
filter(regex(str(?uri),"http://lod.opendata.shiga.jp/otsucity/tourist_attraction")).
}
Objective-CでのGETリクエスト送信部のサンプル
execQueryの部分にさきほどのSPARQLを突っ込む
NSString *endpointurl = @"http://dl.opendata.shiga.jp/sparql?default-graph-uri=http%3A%2F%2Flod.opendata.shiga.jp%2Fhanabi2014&query=";
// ここがポイント
NSString *encodedText = (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(
NULL,
(__bridge CFStringRef)execQuery, //元の文字列
NULL,
CFSTR("!*'();:@&=+$,/?%#[]"),
CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));
NSString *finalreq = [[endpointurl stringByAppendingString:encodedText] stringByAppendingString:@"&format=json"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:finalreq]];
// Accept ヘッダ値は以下の指定に
[request setValue:@"application/sparql-results+json" forHTTPHeaderField:@"Accept"];
NSURLResponse *resp;
NSError *error;
NSData *resdata = [NSURLConnection sendSynchronousRequest:request returningResponse:&resp error:&error];
// jsonに変換
NSMutableArray *jsonResponse = [NSJSONSerialization JSONObjectWithData:resdata
options:kNilOptions
error:nil];
return [[jsonResponse valueForKey:@"results"] valueForKey:@"bindings"];
エンドポイントURLにエンコードしたクエリをひっつけて、
レスポンスの形式をapplication/sparql-results+jsonとし、GETリクエストを投げる。
するとレスポンスはjsonで返ってくる。
jsonを配列に格納して、必要な部分を返り値として渡す。
エラー処理などはしていませんので、あくまで参考に。
NSStringクラスの標準URLエンコードでは、対応しきれていない特殊な文字("!*'();:@&=+$,/?%#[]")がある。
//encoding
NSString *encodedText
= [execQuery stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]
CoreFoundationのCFURLCreateStringByAddingPercentEscapes()を使用
ARC環境では__bridge_transferを使用することでメモリリークを回避
NSString *encodedText = (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(
NULL,
(__bridge CFStringRef)execQuery, //元の文字列
NULL,
CFSTR("!*'();:@&=+$,/?%#[]"),
CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));
次はSwiftでやってみる
CC BY Yuichi Matsuoka /
@you_matz