skos2html 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. data/lib/dcterms.rdf +1089 -0
  2. data/lib/rdf-schema.rdf +131 -0
  3. data/lib/skos.rdf +558 -0
  4. data/lib/skos2html.rb +416 -0
  5. metadata +161 -0
data/lib/skos2html.rb ADDED
@@ -0,0 +1,416 @@
1
+ # encoding: UTF-8
2
+ require 'linkeddata'
3
+ require 'logger'
4
+ require 'builder'
5
+
6
+
7
+ # Converts a SKOS RDF file to a bare-bones HTML file
8
+ # readabale for humans. Rendering a HTML file consists of
9
+ # three basic steps:
10
+ # 1. Create a new instance of this class and specify input and output file.
11
+ # 2. Call load_and_parse.
12
+ # 3. Call generate_html_document.
13
+ # 4. Call the write method.
14
+ class Skos2Html
15
+
16
+ # The output buffer to which we write all HTML.
17
+ attr_accessor :buffer
18
+
19
+ # Initialize the class.
20
+ #
21
+ # @param infile [String], a filepath to a SKOS RDF/XML file
22
+ # @param outfile [String], a filepath where the resulting file will be written (overwriting existing files)
23
+ def initialize(infile=nil, outfile="vocab.html")
24
+ @log = defined?(Rails) ? Rails.logger : Logger.new(STDOUT)
25
+ @log.info("init")
26
+
27
+ @infile = infile
28
+ @outfile = outfile
29
+
30
+ @default_lang = :en
31
+
32
+ @graph = nil
33
+ @vocabs = nil
34
+ set_up_vocabs
35
+
36
+ @buffer = ""
37
+ @builder = Builder::XmlMarkup.new(:target=>@buffer, :indent=>2)
38
+
39
+ @title = ""
40
+
41
+ end
42
+
43
+
44
+ # Load some basic vocabularies in order to retrieve labels
45
+ # etc.
46
+ def set_up_vocabs
47
+ @vocabs = RDF::Graph.load("lib/skos.rdf")
48
+ @vocabs << RDF::Graph.load("lib/dcterms.rdf")
49
+ @vocabs << RDF::Graph.load("lib/rdf-schema.rdf")
50
+ end
51
+
52
+
53
+ # Load the SKOS RDF file into a graph object.
54
+ def load_and_parse
55
+
56
+ if @infile
57
+ @graph = RDF::Graph.load(@infile)
58
+ end
59
+
60
+ end
61
+
62
+
63
+ def generate_html_document
64
+ @builder.declare! :DOCTYPE, :html
65
+
66
+ @builder.html(:lang => @default_lang) { |html|
67
+ generate_html_head
68
+ generate_html_body
69
+ }
70
+ end
71
+
72
+
73
+ def generate_html_body
74
+ @builder.body { |body|
75
+ generate_conceptscheme_info
76
+ generate_concepts
77
+ }
78
+ end
79
+
80
+
81
+ def generate_html_head
82
+
83
+ title = concept_scheme_title
84
+
85
+ @builder.head { |head|
86
+ head.meta(:charset => "UTF-8")
87
+ head.title(title)
88
+ head.meta(:name => "generator", :content => "skos2html")
89
+ head.style("""
90
+ html {
91
+ margin: auto;
92
+ max-width: 800px;
93
+ font-family: Helvetica, Arial, sans-serif;
94
+ }
95
+
96
+ dt {
97
+ font-weight: bold;
98
+ margin: 0.8em 0 0.2em 0;
99
+ }
100
+
101
+ dd {
102
+ margin: 0;
103
+ }
104
+
105
+ dd.contributor {
106
+ display:inline;
107
+ }
108
+
109
+ dd.contributor:after { content: ', '; }
110
+ dd.contributor:last-child:after { content: ''; }
111
+
112
+ dd.identifier {
113
+ font-family: Consolas, 'Lucida Console', 'Courier New', sans-serif;
114
+ }
115
+
116
+ div.conceptscheme {
117
+ border-bottom: 1px solid #aaa;
118
+ margin: 1em 0 2em 0;
119
+ }
120
+
121
+ div.concept {
122
+ margin: 0 0 2.5em 0;
123
+ }
124
+ """)
125
+ }
126
+
127
+ end
128
+
129
+
130
+
131
+ def labels_for(uri)
132
+
133
+ solutions = RDF::Query.execute(@vocabs) do
134
+ pattern [RDF::URI.new(uri), RDF::RDFS.label, :label]
135
+ end
136
+
137
+ result = []
138
+
139
+ if solutions
140
+ solutions.each do |solution|
141
+ # adding RDF literals
142
+ result << solution.label
143
+ end
144
+ end
145
+
146
+ return result
147
+ end
148
+
149
+
150
+
151
+ def string_for(obj, lang)
152
+ # return a human readable representation of obj - for literals the literal
153
+ # value in lang. For URI:s lookup something.
154
+
155
+ case obj
156
+ when String
157
+ return obj
158
+ when RDF::Literal
159
+ if lang
160
+ if obj.language == lang
161
+ return obj.to_s
162
+ else
163
+ return "[Not available in #{lang}]"
164
+ end
165
+ else
166
+ return obj.to_s
167
+ end
168
+ when RDF::URI
169
+ # TODO: fetch it...
170
+ return "[fetched label for #{obj.to_s}]"
171
+ else
172
+ @log.info("unknown class")
173
+ end
174
+ end
175
+
176
+
177
+
178
+ def label_for(uri, lang)
179
+
180
+ @log.info("label_for #{uri} #{lang}")
181
+
182
+ labels = labels_for(uri)
183
+
184
+ @log.info("labels: #{labels.inspect}")
185
+
186
+ if labels
187
+ labels.each do |label|
188
+
189
+ @log.info("label: #{label}")
190
+
191
+ if label.language == lang
192
+ return label.value
193
+ end
194
+ end
195
+ end
196
+ end
197
+
198
+
199
+ def generate_conceptscheme_info
200
+
201
+ conceptschemes = RDF::Query.execute(@graph) do
202
+ pattern [:scheme, RDF.type, RDF::SKOS.ConceptScheme]
203
+ end
204
+
205
+
206
+ @log.info("Concept scheme count #{conceptschemes.size}")
207
+
208
+
209
+ if conceptschemes.size == 1
210
+
211
+ scheme = conceptschemes[0]
212
+ @log.info("Looping concept scheme " + scheme.scheme)
213
+
214
+ scheme_info = RDF::Query.execute(@graph) do
215
+ pattern [scheme.scheme, :predicate, :object]
216
+ end
217
+
218
+ # Title
219
+ title = ""
220
+
221
+ # Description
222
+ description = ""
223
+
224
+ # Creators
225
+ creators = []
226
+
227
+ # Contributors
228
+ contributors = []
229
+
230
+ # get values
231
+ scheme_info.each do |solution|
232
+
233
+ case solution.predicate
234
+ when "http://purl.org/dc/terms/title"
235
+ when "http://www.w3.org/2000/01/rdf-schema#label"
236
+ title = string_for(solution.object, @default_lang)
237
+ when "http://purl.org/dc/terms/description"
238
+ description = string_for(solution.object, @default_lang)
239
+ when "http://purl.org/dc/terms/contributor"
240
+ contributors << string_for(solution.object, nil)
241
+ when "http://purl.org/dc/terms/creator"
242
+ creators << string_for(solution.object, nil)
243
+ end
244
+
245
+ end
246
+
247
+ @builder.div(:class => "conceptscheme") { |html|
248
+
249
+ html.h1(title)
250
+
251
+ html.dl { |html|
252
+
253
+ html.dt("Description")
254
+ html.dd(description, "class" => "description")
255
+
256
+ if contributors.size > 0
257
+ html.dt("Contributors")
258
+
259
+ contributors.each do |item|
260
+ html.dd(item, "class" => "contributor")
261
+ end
262
+ end
263
+
264
+ if creators.size > 0
265
+ html.dt("Creators")
266
+
267
+ creators.each do |item|
268
+ html.dd(item, "class" => "creator")
269
+ end
270
+ end
271
+
272
+ }
273
+ }
274
+
275
+ else
276
+ @log.info("Concept scheme count wrong. Expected 1 was " + conceptschemes.size)
277
+ end
278
+
279
+ end
280
+
281
+
282
+
283
+ def generate_concepts
284
+ concepts = RDF::Query.execute(@graph) do
285
+ pattern [:concept_uri, RDF.type, RDF::SKOS.Concept]
286
+ end
287
+
288
+ @log.info("Concept count: #{concepts.size}")
289
+
290
+ concepts.each do |concept|
291
+ generate_concept(concept.concept_uri)
292
+ end
293
+
294
+ end
295
+
296
+
297
+
298
+
299
+ # Get the title of this vocabulary for use in the HTML
300
+ # title element
301
+ def concept_scheme_title
302
+
303
+ title_properties = ["http://purl.org/dc/terms/title",
304
+ "http://www.w3.org/2000/01/rdf-schema#label",
305
+ "http://www.w3.org/2004/02/skos/core#prefLabel"]
306
+
307
+ title = ""
308
+
309
+ conceptschemes = RDF::Query.execute(@graph) do
310
+ pattern [:scheme, RDF.type, RDF::SKOS.ConceptScheme]
311
+ end
312
+
313
+ if conceptschemes.size == 1
314
+
315
+ scheme = conceptschemes[0]
316
+ @log.info("Looking for title for " + scheme.scheme)
317
+
318
+ scheme_info = RDF::Query.execute(@graph) do
319
+ pattern [scheme.scheme, :predicate, :object]
320
+ end
321
+
322
+ scheme_info.each do |solution|
323
+
324
+ case solution.predicate.to_s
325
+ when *title_properties
326
+ title = solution.object.value
327
+ end
328
+ end
329
+
330
+ return title
331
+
332
+ end
333
+
334
+ end
335
+
336
+
337
+
338
+ # Generate the HTML for an individual concept.
339
+ def generate_concept(concept_uri)
340
+
341
+ concept_info = RDF::Query.execute(@graph) do
342
+ pattern [concept_uri, :predicate, :object]
343
+ end
344
+
345
+ preflabels = []
346
+ altlabels = []
347
+ definition = ""
348
+
349
+ concept_info.each do |solution|
350
+
351
+ case solution.predicate
352
+ when "http://www.w3.org/2004/02/skos/core#prefLabel"
353
+ if solution.object.language?
354
+ preflabels << {"lang" => solution.object.language.to_sym, "val" => solution.object.to_s}
355
+ else
356
+ preflabels << {"lang" => nil, "val" => solution.object.to_s}
357
+ end
358
+ when "http://www.w3.org/2004/02/skos/core#altLabel"
359
+ if solution.object.language?
360
+ altlabels << {"lang" => solution.object.language.to_sym, "val" => solution.object.to_s}
361
+ else
362
+ altlabels << {"lang" => nil, "val" => solution.object.to_s}
363
+ end
364
+ when "http://www.w3.org/2004/02/skos/core#definition"
365
+ definition = string_for(solution.object, @default_lang)
366
+ end
367
+
368
+ end
369
+
370
+
371
+ @builder.div(:id => concept_uri.fragment, :class => "concept") { |html|
372
+ # preflabel in defaultlang
373
+ html.h2(preflabels.detect {|label| label["lang"] == @default_lang}["val"])
374
+ html.dl {
375
+ html.dt("Definition", :class => "definition")
376
+ html.dd(definition, :class => "definition")
377
+
378
+ if altlabels.size > 0
379
+ html.dt("Alternative labels", {:class => "altlabels"})
380
+
381
+ altlabels.each do |label|
382
+
383
+ if label["lang"]
384
+
385
+ if label["lang"] != @default_lang
386
+ html.dd(label["val"] + "(#{label['lang']})", :lang => label["lang"], :class => "altlabel")
387
+ else
388
+ html.dd(label["val"], :class => "altlabel")
389
+ end
390
+
391
+ else
392
+ html.dd(label["val"], :class => "altlabel")
393
+ end
394
+ end
395
+ end
396
+
397
+ html.dt("Identifier", :class => "identifier")
398
+ html.dd(concept_uri, :class => "identifier")
399
+ }
400
+ }
401
+
402
+ end
403
+
404
+
405
+
406
+ # Write the output to disk as an UTF-8 encoded file.
407
+ def write
408
+
409
+ # output to disk
410
+ File.open(@outfile, 'w:UTF-8') { |file|
411
+ file.write(@buffer)
412
+ }
413
+ end
414
+
415
+ end
416
+
metadata ADDED
@@ -0,0 +1,161 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: skos2html
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Peter Krantz
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-07-15 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rdf-rdfxml
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 1.0.2
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 1.0.2
30
+ - !ruby/object:Gem::Dependency
31
+ name: linkeddata
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 1.0.5
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 1.0.5
46
+ - !ruby/object:Gem::Dependency
47
+ name: builder
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: logger
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: rake
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: rspec
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: rspec-html-matchers
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ description: Convert SKOS to a clean readable HTML file.
127
+ email: peter@peterkrantz.se
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - lib/dcterms.rdf
133
+ - lib/rdf-schema.rdf
134
+ - lib/skos.rdf
135
+ - lib/skos2html.rb
136
+ homepage: http://rubygems.org/gems/skos2html
137
+ licenses: []
138
+ post_install_message:
139
+ rdoc_options: []
140
+ require_paths:
141
+ - lib
142
+ required_ruby_version: !ruby/object:Gem::Requirement
143
+ none: false
144
+ requirements:
145
+ - - ! '>='
146
+ - !ruby/object:Gem::Version
147
+ version: '0'
148
+ required_rubygems_version: !ruby/object:Gem::Requirement
149
+ none: false
150
+ requirements:
151
+ - - ! '>='
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
154
+ requirements: []
155
+ rubyforge_project:
156
+ rubygems_version: 1.8.24
157
+ signing_key:
158
+ specification_version: 3
159
+ summary: Simple SKOS to HTML converter
160
+ test_files: []
161
+ has_rdoc: