spreadskos 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/spreadskos.rb +269 -0
- metadata +78 -0
data/lib/spreadskos.rb
ADDED
@@ -0,0 +1,269 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'linkeddata'
|
3
|
+
require 'roo'
|
4
|
+
require 'logger'
|
5
|
+
|
6
|
+
# Creates SKOS files from vocabulary data in a spreadsheet template.
|
7
|
+
class Spreadskos
|
8
|
+
|
9
|
+
def initialize(filepath=nil)
|
10
|
+
|
11
|
+
@log = defined?(Rails) ? Rails.logger : Logger.new(STDOUT)
|
12
|
+
@log.info("init")
|
13
|
+
|
14
|
+
@filepath = filepath
|
15
|
+
@default_lang = :en
|
16
|
+
|
17
|
+
@skos_objs = []
|
18
|
+
setup_skos
|
19
|
+
|
20
|
+
# start new SKOS doc output
|
21
|
+
@graph = RDF::Graph.new
|
22
|
+
|
23
|
+
# Load spreadsheet data
|
24
|
+
@spreadsheet = nil
|
25
|
+
load_spreadsheet(filepath)
|
26
|
+
|
27
|
+
# set up vocab basic info
|
28
|
+
@namespace = "http://example.com/your_namespace/"
|
29
|
+
|
30
|
+
setup_vocab_info
|
31
|
+
|
32
|
+
# Add concepts and related information
|
33
|
+
@concepts = []
|
34
|
+
add_concepts
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
|
40
|
+
# Load SKOS itself to be able to render labels etc later.
|
41
|
+
def setup_skos
|
42
|
+
|
43
|
+
skosfile = File.dirname(__FILE__) + ::File::SEPARATOR + "skos.rdf"
|
44
|
+
@log.info("Load SKOS itself to be able to render labels etc later. File: " + skosfile)
|
45
|
+
|
46
|
+
RDF::Reader.open(skosfile) do |reader|
|
47
|
+
reader.each_statement do |statement|
|
48
|
+
if statement.predicate == "http://www.w3.org/2000/01/rdf-schema#label" then
|
49
|
+
@skos_objs << {:obj => statement.subject.to_s.sub("http://www.w3.org/2004/02/skos/core#",""), :label => statement.object.to_s.downcase.strip}
|
50
|
+
|
51
|
+
@log.info("Adding #{statement.object.to_s.downcase.strip}, #{statement.subject.to_s}")
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
|
60
|
+
def load_spreadsheet(filepath)
|
61
|
+
|
62
|
+
@log.info("Loading #{filepath}")
|
63
|
+
|
64
|
+
if filepath then
|
65
|
+
@spreadsheet = Roo::Spreadsheet.open(filepath)
|
66
|
+
else
|
67
|
+
raise "Spreadsheet not found."
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
|
73
|
+
def setup_vocab_info
|
74
|
+
|
75
|
+
# Build concept scheme info from first sheet
|
76
|
+
info_sheet = @spreadsheet.sheet(0)
|
77
|
+
|
78
|
+
title = ""
|
79
|
+
description = ""
|
80
|
+
version = ""
|
81
|
+
creators = ""
|
82
|
+
contributors = ""
|
83
|
+
|
84
|
+
1.upto(info_sheet.last_row) do |row_no|
|
85
|
+
case info_sheet.cell(row_no, 1)
|
86
|
+
when "Title:"
|
87
|
+
title = info_sheet.cell(row_no, 2)
|
88
|
+
when "Description:"
|
89
|
+
description = info_sheet.cell(row_no, 2)
|
90
|
+
when "Version:"
|
91
|
+
version = info_sheet.cell(row_no, 2)
|
92
|
+
when "Vocabulary identifier:"
|
93
|
+
@namespace = info_sheet.cell(row_no, 2)
|
94
|
+
when "Default language:"
|
95
|
+
@default_lang = info_sheet.cell(row_no, 2).strip
|
96
|
+
when "Creators:"
|
97
|
+
creators = info_sheet.cell(row_no, 2).strip.split(",")
|
98
|
+
when "Contributors:"
|
99
|
+
contributors = info_sheet.cell(row_no, 2).strip.split(",")
|
100
|
+
else
|
101
|
+
puts "Unknown property: " + info_sheet.cell(row_no, 1)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# Write it
|
106
|
+
@graph << [RDF::URI.new(@namespace), RDF.type, RDF::SKOS.ConceptScheme]
|
107
|
+
@graph << [RDF::URI.new(@namespace), RDF::RDFS.label, RDF::Literal.new(title, :language => @default_lang)]
|
108
|
+
@graph << [RDF::URI.new(@namespace), RDF::DC.description, RDF::Literal.new(description, :language => @default_lang)]
|
109
|
+
|
110
|
+
add_creators(creators)
|
111
|
+
|
112
|
+
add_contributors(contributors)
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
|
117
|
+
|
118
|
+
def add_creators(creators)
|
119
|
+
@log.info("adding creators")
|
120
|
+
|
121
|
+
creators.each do |creator|
|
122
|
+
@graph << [RDF::URI.new(@namespace), RDF::DC.creator, RDF::Literal.new(creator.strip)]
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
|
127
|
+
|
128
|
+
def add_contributors(contributors)
|
129
|
+
@log.info("adding contributors")
|
130
|
+
|
131
|
+
contributors.each do |contributor|
|
132
|
+
@graph << [RDF::URI.new(@namespace), RDF::DC.contributor, RDF::Literal.new(contributor.strip)]
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
|
137
|
+
def add_concepts
|
138
|
+
|
139
|
+
@log.info("adding concepts")
|
140
|
+
|
141
|
+
# Add concepts and labels from second worksheet
|
142
|
+
concept_sheet = @spreadsheet.sheet(1)
|
143
|
+
|
144
|
+
columns = []
|
145
|
+
|
146
|
+
# Build column model
|
147
|
+
1.upto(concept_sheet.last_column) do |col_no|
|
148
|
+
@log.info("\tcol: " + concept_sheet.cell(1, col_no))
|
149
|
+
columns << concept_sheet.cell(1, col_no)
|
150
|
+
end
|
151
|
+
|
152
|
+
|
153
|
+
# Iterate rows
|
154
|
+
2.upto(concept_sheet.last_row) do |row_no|
|
155
|
+
|
156
|
+
# Concepts fragments are in the first column
|
157
|
+
concept_fragment_id = concept_sheet.cell(row_no, 1)
|
158
|
+
|
159
|
+
if concept_fragment_id.size > 0 then
|
160
|
+
|
161
|
+
concept = uri_for_concept_fragment(concept_fragment_id)
|
162
|
+
@log.info("concept: " + concept)
|
163
|
+
|
164
|
+
# Add concept to graph
|
165
|
+
@graph << [concept, RDF.type, RDF::SKOS.Concept]
|
166
|
+
|
167
|
+
# Connect it to the concept scheme
|
168
|
+
add_concept_to_scheme(concept)
|
169
|
+
|
170
|
+
#loop columns for concept
|
171
|
+
2.upto(concept_sheet.last_column) do |col_no|
|
172
|
+
|
173
|
+
# What property is this?
|
174
|
+
property, lang = skosname_and_lang_from_column_head(columns[col_no - 1])
|
175
|
+
@log.info("Prop+lang: #{property}, #{lang}")
|
176
|
+
|
177
|
+
#Value
|
178
|
+
value = concept_sheet.cell(row_no, col_no)
|
179
|
+
@log.info("Val: #{value}")
|
180
|
+
|
181
|
+
# literal?
|
182
|
+
if value and value.strip.size > 0
|
183
|
+
if value.start_with?("#") or value.start_with?("http")
|
184
|
+
# Add this property to the graph
|
185
|
+
add_property_to_graph(concept, property, value)
|
186
|
+
else
|
187
|
+
value = RDF::Literal.new(value, :language => lang)
|
188
|
+
add_property_to_graph(concept, property, value)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
end
|
196
|
+
|
197
|
+
end
|
198
|
+
|
199
|
+
|
200
|
+
|
201
|
+
def add_property_to_graph(concept, property, value)
|
202
|
+
@graph << [concept, property, value]
|
203
|
+
end
|
204
|
+
|
205
|
+
|
206
|
+
|
207
|
+
def add_concept_to_scheme(concept)
|
208
|
+
@graph << [concept, RDF::SKOS.inScheme, @namespace]
|
209
|
+
end
|
210
|
+
|
211
|
+
|
212
|
+
|
213
|
+
|
214
|
+
def uri_for_concept_fragment(fragment)
|
215
|
+
if fragment.downcase.start_with?("http") then
|
216
|
+
# user edited their own concept identifier
|
217
|
+
return RDF::URI.new(fragment)
|
218
|
+
else
|
219
|
+
# make local identifier
|
220
|
+
return RDF::URI.new(@namespace + fragment)
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
|
225
|
+
|
226
|
+
def skosname_and_lang_from_column_head(column)
|
227
|
+
|
228
|
+
@log.info("\t Mapping column #{column}")
|
229
|
+
|
230
|
+
# find skos property from column header text (e.g. "Preferred label (en)")
|
231
|
+
label, lang = column.split("(")
|
232
|
+
if lang then
|
233
|
+
lang = lang.sub(")","").to_sym
|
234
|
+
else
|
235
|
+
# Default lang
|
236
|
+
lang = @default_lang
|
237
|
+
end
|
238
|
+
|
239
|
+
skosprop = skos_from_label(label)
|
240
|
+
|
241
|
+
@log.info("skosprop: #{skosprop}")
|
242
|
+
|
243
|
+
return skosprop, lang
|
244
|
+
end
|
245
|
+
|
246
|
+
|
247
|
+
|
248
|
+
def skos_from_label(label)
|
249
|
+
@log.info("Looking up >#{label.downcase.strip}<")
|
250
|
+
|
251
|
+
prop = @skos_objs.select {|o| o[:label] == label.downcase.strip }
|
252
|
+
|
253
|
+
@log.info(prop)
|
254
|
+
|
255
|
+
return eval("RDF::SKOS." + prop[0][:obj])
|
256
|
+
end
|
257
|
+
|
258
|
+
|
259
|
+
def write_graph(filename="result.rdf", format=:rdfxml)
|
260
|
+
|
261
|
+
puts @graph.dump(:rdfxml)
|
262
|
+
|
263
|
+
File.open(filename, 'w') { |file|
|
264
|
+
file.write(@graph.dump(format))
|
265
|
+
}
|
266
|
+
|
267
|
+
end
|
268
|
+
|
269
|
+
end
|
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: spreadskos
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Peter Krantz
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-07-11 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rspec
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
description: Convert vocabularies created in a spreadsheet template to SKOS.
|
47
|
+
email: peter@peterkrantz.se
|
48
|
+
executables: []
|
49
|
+
extensions: []
|
50
|
+
extra_rdoc_files: []
|
51
|
+
files:
|
52
|
+
- lib/spreadskos.rb
|
53
|
+
homepage: http://rubygems.org/gems/spreadskos
|
54
|
+
licenses: []
|
55
|
+
post_install_message:
|
56
|
+
rdoc_options: []
|
57
|
+
require_paths:
|
58
|
+
- lib
|
59
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
60
|
+
none: false
|
61
|
+
requirements:
|
62
|
+
- - ! '>='
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: '0'
|
65
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ! '>='
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
requirements: []
|
72
|
+
rubyforge_project:
|
73
|
+
rubygems_version: 1.8.24
|
74
|
+
signing_key:
|
75
|
+
specification_version: 3
|
76
|
+
summary: Spreadskos
|
77
|
+
test_files: []
|
78
|
+
has_rdoc:
|