2014/09/05

Objective-CでのSPARQL利用

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