skos2html 0.0.2

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.
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: