「図書館及び関連組織のための国際標準識別子(ISIL)」を触ってみた

2015年5月8日に追記しました.

はじめに

先日NDLで新しいデータとして図書館及び関連組織のための国際標準識別子(ISIL)が公開されました.
オープンデータセット | 国立国会図書館-National Diet Library

RDF形式のデータで馴染みがなかったので,簡単に触ってみました.*1

環境

RDF形式のファイルを扱うためには今回はlinkeddataというgemを使いました.
RDF以外の形式のデータも扱うことができるGemです.

$ gem isntall linkeddata

データ

NDLのサイトから公共図書館のデータをダウンロードすると
isilpublic.rdf
というデータがあるかと思います.

このデータから図書館名,経度,緯度を取り出してみます.

1館分のデータは,以下のようになっています.

<rdf:Description rdf:about="http://id.ndl.go.jp/vocab/isil/JP-1000031">
	<rdf:type rdf:resource="http://schema.org/Organization"/>
	<dcterms:identifier rdf:datatype="http://ndl.go.jp/dcndl/terms/ISIL">JP-1000031</dcterms:identifier>
	<dbpedia:originalName xml:lang="ja">北海道立図書館</dbpedia:originalName>
	<schema:name xml:lang="ja">北海道立図書館</schema:name>
	<schema:name xml:lang="ja-kana">ホッカイドウリツトショカン</schema:name>
	<schema:name xml:lang="en">Hokkaido Prefectural Library</schema:name>
	<org:classification rdf:resource="http://id.ndl.go.jp/vocab/libtype#PublicLibraries"/>
	<owl:sameAs rdf:resource="http://id.ndl.go.jp/auth/entity/00265285"/>
	<dcterms:identifier rdf:datatype="http://ndl.go.jp/dcndl/terms/NDLLibCode">0111</dcterms:identifier>
	<owl:sameAs rdf:resource="http://ci.nii.ac.jp/library/FA010697"/>
	<owl:sameAs rdf:resource="http://ja.dbpedia.org/resource/北海道立図書館"/>
	<schema:URL rdf:resource="http://www.library.pref.hokkaido.jp"/>
</rdf:Description>

<rdf:Description rdf:nodeID="node19hvo1bd5x1">
	<rdf:type rdf:resource="http://www.w3.org/ns/org#Site"/>
</rdf:Description>

<rdf:Description rdf:nodeID="node19hvo1bd5x2">
	<schema:postalCode>069-0834</schema:postalCode>
	<schema:addressCountry>Japan</schema:addressCountry>
	<gn:countryCode>JP</gn:countryCode>
	<schema:areaServed rdf:resource="http://statdb.nstac.go.jp/lod/sac/C01217"/>
	<schema:addressRegion>北海道</schema:addressRegion>
	<schema:addressLocality>江別市</schema:addressLocality>
	<schema:streetAddress>文京台東町41</schema:streetAddress>
</rdf:Description>

<rdf:Description rdf:nodeID="node19hvo1bd5x1">
	<org:siteAddress rdf:nodeID="node19hvo1bd5x2"/>
	<geo:long>141.50093</geo:long>
	<geo:lat>43.06999</geo:lat>
	<schema:telephone>011-386-8521</schema:telephone>
	<schema:faxNumber>011-386-6906</schema:faxNumber>
</rdf:Description>

<rdf:Description rdf:about="http://id.ndl.go.jp/vocab/isil/JP-1000031">
	<org:hasSite rdf:nodeID="node19hvo1bd5x1"/>
</rdf:Description>

コード

statementがRDFの1つの文を指します.
predicateがstatementの述語
objectがstatementの目的語を表しています.

上の例だと
北海道立図書館

  • predicateがoriginalName
  • objectが北海道立図書館

に相当します.

originalNameが複数個ついているデータがありますが,
今回は複数あった場合は,最後のobjectだけを出力しています.

require 'linkeddata'

data = []
RDF::RDFXML::Reader.open("./isilpublic.rdf") do |reader|
  reader.each_statement do |statement|
    predicate = statement.predicate.to_s.split("/")[-1]
    data[0] = statement.object if predicate == 'originalName'
    data << statement.object if predicate == 'wgs84_pos#long'
    data << statement.object if predicate == 'wgs84_pos#lat'
 
    if predicate == 'wgs84_pos#lat'
      puts data.join(',')
      data.clear
    end
  end
end

これを実行すると,以下の様な出力が得られます.

北海道立図書館,141.50093,43.06999
札幌市中央図書館,141.34044,43.0298
札幌市山の手図書館,141.29652,43.07239
札幌市新琴似図書館,141.32909,43.11296
札幌市西岡図書館,141.38773,43.01332
札幌市澄川図書館,141.36842,43.01249
札幌市元町図書館,141.37161,43.10046
札幌市厚別図書館,141.47453,43.03628
札幌市曙図書館,141.23999,43.12648
札幌市東札幌図書館,141.3907,43.05097
札幌市清田図書館,141.44339,42.9998
函館市中央図書館,140.75352,41.79825
市立小樽図書館,140.99361,43.19005
旭川市中央図書館,142.35995,43.77658
旭川市末広図書館,142.37894,43.80692
旭川市永山図書館,142.43631,43.81064
旭川市東光図書館,142.40079,43.7496
...

全部で4881件ありました.

おわりに

電話番号や住所,URLなど連絡するための情報もRDFに記述されているので,何かと便利かもしれません.

追記(2015/05/08)

ightさまから,はてなブックマークでコメントを頂きました.
のほうを使ってください!!!!!!」



さっそく使ってみると,

require 'linkeddata'

data = []
RDF::RDFXML::Reader.open("./isilpublic.rdf") do |reader|
  reader.each_statement do |statement|

    predicate = statement.predicate.to_s.split("/")[-1]
    if predicate == 'name'
      data << statement.object if statement.object.language == :ja
    end 
    data << statement.object if predicate == 'wgs84_pos#long'
    data << statement.object if predicate == 'wgs84_pos#lat'

    if predicate == 'wgs84_pos#lat'
      puts data.join(',')
      data.clear
    end
  end
end

となります.

nameはlanguageに応じて複数あるため,日本語名のみを取り出すには

data << statement.object if statement.object.language == :ja

とする必要があります

ただし,今回に限ってしまうと,日本語名はかならずnameの先頭にあるので

data << predicate == 'name' # && data.size == 0

としてもうまくいきます.


ご指摘を頂いたお陰で,languageを指定する方法がわかりました.
ightさまありがとうございました.

*1:そもそもRDFの用語に馴染みがなかった