spread2rdf 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/README.md +434 -5
- data/VERSION +1 -1
- data/examples/ProSysMod.s2r.rb +334 -0
- data/lib/spread2rdf/mapping/cell.rb +4 -7
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
ODFlMzQ3MWRiYzJhMmU5MzI5Mzk0MGZhMWE1NDMyNGZjYjZiNWYxMw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
YTE1MzNmNzhlMjI1ODc2ZDlhMzVlY2Q3Y2NkZDUzNDY2MWViZmY4Mw==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
ZTA3MzY0YzQ3ZTUxZmMzNTRlNjkzYjdjNjFmZGVhNjY3YTc1M2MxODQ5YzUz
|
10
|
+
M2MyYjc0MjJhYzQzZTBlNGU5YzdjZDk0Nzk1Mzg3ZmI3ZTNlOGY1ZTM3MTVi
|
11
|
+
Y2Y4ODZlYzk0NjljYTVjZDYwMmY1MGMyZTQ3ZDI0NjhkNTQwMjk=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
ZmVjMGQwNGZlY2MzMjJmZDQwOGFkZTMxMTc1YWQyZTU5NzY3YmU1MDczYzE3
|
14
|
+
NTQyZmFmOWY3Nzk5ZGZiMjJhOWJmYjdmZGM3ZTVhMGYxMzMwNDM2M2MxY2Ey
|
15
|
+
NzVhNWVlZTRkM2M0ZGIxMTljMDEyYTZjYjQ0ZDRmOTgzYjIzNDc=
|
data/README.md
CHANGED
@@ -9,20 +9,449 @@ for specifying the mapping rules for this conversion.
|
|
9
9
|
* Supports Excel/Excelx, Google spreadsheets, OpenOffice, LibreOffice and CSV
|
10
10
|
spreadsheets as input, thanks to [Roo](https://github.com/Empact/roo).
|
11
11
|
(Currently, it's tested for Excel only.
|
12
|
-
If you have
|
12
|
+
If you have problems with other spreadsheet types,
|
13
13
|
[raise an issue](https://github.com/marcelotto/spread2rdf/issues).)
|
14
14
|
* Supports many RDF serialization formats for the output, thanks to
|
15
15
|
[RDF.rb](https://github.com/ruby-rdf/rdf).
|
16
|
-
* Mapping definitions
|
17
|
-
Ruby installed
|
16
|
+
* Mapping definitions can be compiled to executables, which are runnable without
|
17
|
+
having Ruby installed
|
18
18
|
|
19
19
|
## Installation
|
20
20
|
|
21
|
-
Install [Ruby](http://www.ruby-lang.org/) and execute
|
22
|
-
in a terminal:
|
21
|
+
Install [Ruby](http://www.ruby-lang.org/) and execute:
|
23
22
|
|
24
23
|
$ gem install spread2rdf
|
25
24
|
|
25
|
+
## Command-line interface
|
26
|
+
|
27
|
+
For a full description of available parameters, run:
|
28
|
+
|
29
|
+
$ spread2rdf --help
|
30
|
+
|
31
|
+
## How it works
|
32
|
+
|
33
|
+
Write a mapping file for the spreadsheet that should be converted to RDF.
|
34
|
+
Apply the mapping using the ```spread2rdf```
|
35
|
+
command-line interface or a compiled version of the mapping file.
|
36
|
+
|
37
|
+
### Example mapping file
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
require 'spread2rdf'
|
41
|
+
|
42
|
+
module Spread2RDF
|
43
|
+
Schema.definition 'ProSysMod-Data' do
|
44
|
+
|
45
|
+
namespaces(
|
46
|
+
PSM: 'http://example.com/ProSysMod/ontology#',
|
47
|
+
QUDT: 'http://qudt.org/schema/qudt#'
|
48
|
+
)
|
49
|
+
|
50
|
+
worksheet 'RDF-Export', name: :Settings do
|
51
|
+
NS[:Base] = cell(:B7)
|
52
|
+
NS[:PSM_MaterialElement] = cell(:B9)
|
53
|
+
end
|
54
|
+
|
55
|
+
worksheet 'MaterialelementeKlassen',
|
56
|
+
name: :MaterialElementClasses,
|
57
|
+
start: :B5,
|
58
|
+
subject: { uri: { namespace: PSM_MaterialElement },
|
59
|
+
type: RDF::RDFS.Class,
|
60
|
+
sub_class_of: PSM.MaterialElement
|
61
|
+
} do
|
62
|
+
column :name, predicate: RDFS.label
|
63
|
+
column :uri
|
64
|
+
|
65
|
+
column :sub_class_of, predicate: RDFS.subClassOf,
|
66
|
+
object: { from: :MaterialElementClasses }
|
67
|
+
column_block :parameter, subject: { uri: :bnode, type: PSM.Parameter },
|
68
|
+
predicate: PSM.materialParameter,
|
69
|
+
statement: :restriction do
|
70
|
+
column :name, predicate: PSM.parameterName
|
71
|
+
column :description, predicate: PSM.parameterDescription
|
72
|
+
|
73
|
+
column :min, predicate: PSM.parameterMinQuantity,
|
74
|
+
object: { uri: :bnode, type: QUDT.QuantityValue },
|
75
|
+
&quantity_mapping
|
76
|
+
column :exact, predicate: PSM.parameterQuantity,
|
77
|
+
object: { uri: :bnode, type: QUDT.QuantityValue },
|
78
|
+
&quantity_mapping
|
79
|
+
column :max, predicate: PSM.parameterMaxQuantity,
|
80
|
+
object: { uri: :bnode, type: QUDT.QuantityValue },
|
81
|
+
&quantity_mapping
|
82
|
+
column :unit, object: lambda do |value|
|
83
|
+
statements(
|
84
|
+
[ object, QUDT.numericValue, value.to_i ],
|
85
|
+
[ object, QUDT.unit, object_of_column(:unit) ] )
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
worksheet 'Materialelemente',
|
91
|
+
name: :MaterialElements,
|
92
|
+
start: :B5,
|
93
|
+
subject: { uri: { namespace: PSM_MaterialElement },
|
94
|
+
type: PSM.MaterialElement
|
95
|
+
} do
|
96
|
+
column :name, predicate: RDFS.label
|
97
|
+
column :uri
|
98
|
+
|
99
|
+
column :type, predicate: RDF.type,
|
100
|
+
object: { from: :MaterialElementClasses }
|
101
|
+
column_block :parameter, subject: { uri: :bnode, type: PSM.Parameter },
|
102
|
+
predicate: PSM.materialParameter,
|
103
|
+
¶meter_block
|
104
|
+
|
105
|
+
column_block :parameter, subject: { uri: :bnode, type: PSM.Parameter },
|
106
|
+
predicate: PSM.materialParameter do
|
107
|
+
column :name, predicate: PSM.parameterName
|
108
|
+
column :description, predicate: PSM.parameterDescription
|
109
|
+
|
110
|
+
column :min, predicate: PSM.parameterMinQuantity,
|
111
|
+
object: { uri: :bnode, type: QUDT.QuantityValue },
|
112
|
+
&quantity_mapping
|
113
|
+
column :exact, predicate: PSM.parameterQuantity,
|
114
|
+
object: { uri: :bnode, type: QUDT.QuantityValue },
|
115
|
+
&quantity_mapping
|
116
|
+
column :max, predicate: PSM.parameterMaxQuantity,
|
117
|
+
object: { uri: :bnode, type: QUDT.QuantityValue },
|
118
|
+
&quantity_mapping
|
119
|
+
column :unit, object: lambda do |value|
|
120
|
+
statements(
|
121
|
+
[ object, QUDT.numericValue, value.to_i ],
|
122
|
+
[ object, QUDT.unit, object_of_column(:unit) ] )
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
```
|
129
|
+
|
130
|
+
A complete example file, showcasing most of the features, can be found
|
131
|
+
[in the examples directory](examples/ProSysMod.s2r.rb).
|
132
|
+
|
133
|
+
### Mapping definition file
|
134
|
+
|
135
|
+
A mapping file is a Ruby file containing a definition like this:
|
136
|
+
|
137
|
+
```ruby
|
138
|
+
require 'spread2rdf'
|
139
|
+
|
140
|
+
module Spread2RDF
|
141
|
+
Schema.definition 'Name-of-the-mapping-schema' do
|
142
|
+
|
143
|
+
end
|
144
|
+
end
|
145
|
+
```
|
146
|
+
|
147
|
+
The name is purely descriptive and currently not used for anything else.
|
148
|
+
The definition block contains the description of your spreadsheets schema and
|
149
|
+
the conversion rules for mapping the cells to RDF.
|
150
|
+
|
151
|
+
### URIs and namespaces
|
152
|
+
|
153
|
+
URIs can be written in the form ```Namespace.suffix```, where the namespace is
|
154
|
+
written in uppercase.
|
155
|
+
The most common namespaces like ```RDF, RDFS, OWL, SKOS, XSD, DC, FOAF``` (all
|
156
|
+
predefined [RDF.rb vocabularies](http://rubydoc.info/github/ruby-rdf/rdf/master/RDF/Vocabulary))
|
157
|
+
are available without prior declaration.
|
158
|
+
Additional namespaces can be defined statically using the ```namespace``` method
|
159
|
+
in the schema definition block:
|
160
|
+
```ruby
|
161
|
+
module Spread2RDF
|
162
|
+
Schema.definition 'Name-of-the-mapping-schema' do
|
163
|
+
namespaces(
|
164
|
+
EX: 'http://www.example.com/',
|
165
|
+
QUDT: 'http://qudt.org/schema/qudt#'
|
166
|
+
)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
```
|
170
|
+
If you want to declare a namespace dynamically, from the contents
|
171
|
+
of a cell for example, an element can be added to the hash of namespaces
|
172
|
+
```NS```. The name is given as a Ruby symbol:
|
173
|
+
```ruby
|
174
|
+
worksheet 'Settings' do
|
175
|
+
NS[:EX] = cell(:B7)
|
176
|
+
end
|
177
|
+
```
|
178
|
+
|
179
|
+
### Worksheet schema definitions
|
180
|
+
The schema definition block should contain a worksheet definition for every
|
181
|
+
worksheet to be processed.
|
182
|
+
It consists of
|
183
|
+
- the keyword ```worksheet```,
|
184
|
+
- followed by the name of the worksheet used in the spreadsheet as a string,
|
185
|
+
- a list of named parameters (described below),
|
186
|
+
- and a block with column or column block definitions or arbitrary cell
|
187
|
+
processing as in the ```Settings``` worksheet above.
|
188
|
+
The order of the worksheet definitions is not significant.
|
189
|
+
|
190
|
+
###### ```name``` parameter
|
191
|
+
If you want to refer to a worksheet (e.g. in the ```subject``` parameter) with
|
192
|
+
a different name than the one used in the spreadsheet (because it contains
|
193
|
+
whitespaces for example), you can define it with this parameter.
|
194
|
+
|
195
|
+
###### ```start``` parameter
|
196
|
+
A Ruby symbol pointing to the upper-left cell of the data to be converted.
|
197
|
+
Assuming the first row is a header (which is irrelevant for the conversion), the
|
198
|
+
default value for this parameter is ```:A2```.
|
199
|
+
|
200
|
+
###### ```subject``` parameter
|
201
|
+
This parameter specifies the construction of subject resources from rows.
|
202
|
+
It expects a hash with further sub-parameters as its value:
|
203
|
+
- ```uri```: Defines the rules to construct an URI for the subject.
|
204
|
+
Possible values are:
|
205
|
+
- ```:bnode```: Construct a blank node for every subject.
|
206
|
+
- Another hash if a full URI should be constructed with the following possible
|
207
|
+
parameters:
|
208
|
+
- ```column```: The name of a column as a Ruby symbol, which contains the
|
209
|
+
base value for the construction of an URI for a subject.
|
210
|
+
In the following I will call this the subject column.
|
211
|
+
The default value for this is ```:uri```.
|
212
|
+
- ```namespace```: The namespace used to construct an URI for a subject by
|
213
|
+
concatenation with the corresponding value of the subject column.
|
214
|
+
If this is not specified, it is assumed that the subject column contains
|
215
|
+
absolute URIs.
|
216
|
+
- ```type```: The URI of the RDFS class every subject should be an element of,
|
217
|
+
i.e. for every subject a ```rdf:type``` statement is produced with this URI as
|
218
|
+
its object.
|
219
|
+
- ```sub_class_of```: The URI of a RDFS class every subject should be a
|
220
|
+
```rdfs:subClassOf``` of,
|
221
|
+
i.e. for every subject a ```rdfs:subClassOf``` statement is produced with
|
222
|
+
this URI as its object.
|
223
|
+
- ```column```: shortcut for the ```column``` sub-parameter of the ```uri``` parameter
|
224
|
+
|
225
|
+
Note that the rows for a subject might span multiple rows of a worksheet, for
|
226
|
+
example when a column contains multiple rows with values for the same subject.
|
227
|
+
The range of rows for a subject is defined by the subject column according to
|
228
|
+
the following criteria:
|
229
|
+
- The first row for a subject is the row with a non-empty value in the subject
|
230
|
+
column (by default the column ```:uri```).
|
231
|
+
- The last row for a subject is the last row with an empty value in the subject
|
232
|
+
column or the last row of the worksheet.
|
233
|
+
|
234
|
+
### Column schema definitions
|
235
|
+
A column definition consists of
|
236
|
+
- the keyword ```column```,
|
237
|
+
- followed by a Ruby symbol with the arbitrary name of the column,
|
238
|
+
- an optional list of named parameters (described below),
|
239
|
+
- and an optional block with custom logic (described below).
|
240
|
+
The order of column definitions is significant and must correspond to the
|
241
|
+
order of columns in the worksheet.
|
242
|
+
For columns which should be ignored, the parameters must be omitted.
|
243
|
+
Note, that the first column is defined by the ```start``` parameter of the
|
244
|
+
worksheet.
|
245
|
+
|
246
|
+
###### ```predicate``` parameter
|
247
|
+
The URI of the RDF property which should be used for constructing of triples for
|
248
|
+
values of this column.
|
249
|
+
Leaving this parameter unspecified has the same effect as setting ```statement```
|
250
|
+
to ```:none``` (see below).
|
251
|
+
|
252
|
+
###### ```object``` parameter
|
253
|
+
This parameter specifies the construction of an object resource or value for a
|
254
|
+
row and expects a hash with further sub-parameters as its value:
|
255
|
+
- ```language```:
|
256
|
+
A string or Ruby symbol with a language to be used to tag the string value of
|
257
|
+
the generated triple.
|
258
|
+
- ```uri```:
|
259
|
+
Specifies the rule for the generation of a resource for the object
|
260
|
+
of a triple. Currently, the following values are possible:
|
261
|
+
- ```:bnode```:
|
262
|
+
Generate a blank node. Primarily used in conjunction with the specification
|
263
|
+
of a Ruby block for custom logic (see below), where additional statements
|
264
|
+
about this object are generated.
|
265
|
+
- A Hash with a ```namespace``` key and a namespace as the value, which is
|
266
|
+
used to construct an URI by concatenating it with the corresponding cell
|
267
|
+
value of the column.
|
268
|
+
- ```type```:
|
269
|
+
The URI of the RDFS class every object resource should be an element of, i.e.
|
270
|
+
for every object a ```rdf:type``` statement is produced with this URI as its
|
271
|
+
object.
|
272
|
+
- ```from```:
|
273
|
+
Allows the specification of other data sources from which a resource is
|
274
|
+
referenced with a value of the column.
|
275
|
+
The graph of this data source is therefore queried for a resource with the
|
276
|
+
value of the column as its ```rdfs:label``` (currently this property is hard
|
277
|
+
coded, but could be made configurable).
|
278
|
+
The value of this parameter can be a Hash with one or a combination of the
|
279
|
+
following keys or a single Ruby symbol as a shortcut ```worksheet``` or a
|
280
|
+
single string or hash as a shortcut for ```data_source```.
|
281
|
+
- ```worksheet```: The name of a worksheet, whose generated output graph
|
282
|
+
should be queried.
|
283
|
+
- ```data_source```: A single filename or an array of filenames of RDF files,
|
284
|
+
which should be queried.
|
285
|
+
In case of relative paths the directory of the input spreadsheet and the
|
286
|
+
directories specified with the ```-I``` CLI parameter are used for the file
|
287
|
+
search.
|
288
|
+
Although not tested, also URLs to hosted RDF data should be possible instead
|
289
|
+
of filenames, due to RDF.rb.
|
290
|
+
Instead of a hash with object construction parameter, it is also possible to
|
291
|
+
specify a Ruby proc with arbitrary object construction logic.
|
292
|
+
This block gets the value of a cell and should return the mapped value to be
|
293
|
+
used as the object of the corresponding generated triple.
|
294
|
+
|
295
|
+
###### ```statement``` parameter
|
296
|
+
This parameter allows the configuration of the triple generation.
|
297
|
+
Currently, the following values are possible:
|
298
|
+
- ```:none```:
|
299
|
+
Don't generate a triple.
|
300
|
+
Useful in conjunction with Ruby blocks for custom logic.
|
301
|
+
Leaving the ```predicate``` parameter unspecified has the same effect.
|
302
|
+
- ```:inverse```:
|
303
|
+
Use the subject resource (from the subject column) as the object and the
|
304
|
+
mapped value of a cell as the subject of the generated statement.
|
305
|
+
- ```:restriction```:
|
306
|
+
This parameter value makes only sense, when the subject is a OWL class.
|
307
|
+
Instead of generating a triple of the form
|
308
|
+
```subject predicate object .```,
|
309
|
+
where ```subject``` is the resource from the subject column,
|
310
|
+
```predicate``` the value specified in the ```predicate``` parameter,
|
311
|
+
and ```object``` the mapped value from the cell of a column,
|
312
|
+
the following statements are generated:
|
313
|
+
|
314
|
+
```
|
315
|
+
subject rdfs:subClassOf [
|
316
|
+
rdf:type owl:Restriction ;
|
317
|
+
owl:onProperty predicate ;
|
318
|
+
restriction_property object
|
319
|
+
] .
|
320
|
+
```
|
321
|
+
|
322
|
+
```restriction_property``` is ```owl:hasValue``` by default, but can be
|
323
|
+
changed by giving a hash as the value of ```statement``` parameter, containing
|
324
|
+
```:restriction``` as a key and the URI of restriction property as its value.
|
325
|
+
|
326
|
+
###### Custom logic with Ruby blocks
|
327
|
+
The optional Ruby block can be used to generate further statements (or perform
|
328
|
+
custom actions in general) to the values of a column.
|
329
|
+
This block gets the cell value as an argument, but is executed in the context of
|
330
|
+
the [Cell class](lib/spread2rdf/mapping/cell.rb), so the mapped value can be
|
331
|
+
accessed via the ```object``` method.
|
332
|
+
It's also possible to access the value or mapped value of another column of the
|
333
|
+
same row with the methods ```value_of_column``` or ```object_of_column```.
|
334
|
+
A single statement can be generated with the ```statement``` method, which
|
335
|
+
expects three arguments for the subject, predicate and object.
|
336
|
+
Multiple statements at once can be generated with the ```statements``` method,
|
337
|
+
which takes an arbitrary number of array arguments containing the three subject,
|
338
|
+
predicate and object elements of a triple.
|
339
|
+
|
340
|
+
### Column block definitions
|
341
|
+
A column block is used to define a sub sheet of a worksheet, meaning a series of
|
342
|
+
columns (or further columns blocks) which are treated like a sheet, i.e.
|
343
|
+
introducing subject resources, which are used as the subject of the triples
|
344
|
+
generated for these columns, while the subjects itself become objects of the
|
345
|
+
triples for the outer sheet (or column block).
|
346
|
+
|
347
|
+
A column block definition consists of
|
348
|
+
- the keyword ```column_block```,
|
349
|
+
- followed by a Ruby symbol with an arbitrary name of the column block,
|
350
|
+
- an optional list of named parameters,
|
351
|
+
- and a Ruby block with column or further column block definitions.
|
352
|
+
All parameters of worksheets (except ```start```) and columns (the ```object```
|
353
|
+
parameter) can be used as parameters of a column block definition.
|
354
|
+
|
355
|
+
### Templates
|
356
|
+
Templates are a way to associate a name with a Ruby block in a worksheet,
|
357
|
+
for later reuse of definition blocks or mapping blocks.
|
358
|
+
A template definition consists of
|
359
|
+
- the keyword ```template```,
|
360
|
+
- followed by a name as a Ruby symbol,
|
361
|
+
- and a block.
|
362
|
+
After a template definition the block can be accessed directly by using the defined
|
363
|
+
name.
|
364
|
+
|
365
|
+
Example:
|
366
|
+
```ruby
|
367
|
+
module Spread2RDF
|
368
|
+
Schema.definition 'Example' do
|
369
|
+
template :quantity_mapping do |value|
|
370
|
+
statements(
|
371
|
+
[ object, QUDT.numericValue, value.to_i ],
|
372
|
+
[ object, QUDT.unit, object_of_column(:unit) ] )
|
373
|
+
end
|
374
|
+
|
375
|
+
worksheet 'Example sheet' do
|
376
|
+
column :uri
|
377
|
+
column :value, predicate: PSM.parameterMaxQuantity,
|
378
|
+
object: { uri: :bnode, type: QUDT.QuantityValue },
|
379
|
+
&quantity_mapping
|
380
|
+
column :unit, object: unit_mapping # unit_mapping is a predefined custom object mapping to QUDT units
|
381
|
+
end
|
382
|
+
end
|
383
|
+
end
|
384
|
+
```
|
385
|
+
|
386
|
+
Another usage for templates is the definition of a sequence of columns in a worksheet
|
387
|
+
definition, by calling the ```include``` method with the template name (in this case
|
388
|
+
as Ruby symbol) in a worksheet definition (at the appropriate position).
|
389
|
+
|
390
|
+
Example:
|
391
|
+
```ruby
|
392
|
+
module Spread2RDF
|
393
|
+
Schema.definition 'Example' do
|
394
|
+
template :default_columns do
|
395
|
+
column :name, predicate: RDFS.label
|
396
|
+
column :uri
|
397
|
+
end
|
398
|
+
|
399
|
+
worksheet 'Example sheet' do
|
400
|
+
include :default_columns
|
401
|
+
end
|
402
|
+
end
|
403
|
+
end
|
404
|
+
```
|
405
|
+
|
406
|
+
## Executable mappings
|
407
|
+
It's possible to make a schema mapping definition executable as a command-line
|
408
|
+
application by placing a ```Schema.execute``` call after the schema definition
|
409
|
+
in a mapping file.
|
410
|
+
With that, the mapping file can be used as an executable script file, which
|
411
|
+
behaves like ```spread2rdf``` with the schema mapping parameter ```-s```
|
412
|
+
implicitly set to this schema mapping, supporting all of its possible
|
413
|
+
parameters (except ```-s``` obviously).
|
414
|
+
|
415
|
+
Example: A file ```example-mapping.s2r``` with the following definition
|
416
|
+
```ruby
|
417
|
+
#!/usr/bin/env ruby
|
418
|
+
|
419
|
+
module Spread2RDF
|
420
|
+
Schema.definition 'Example' do
|
421
|
+
# ...
|
422
|
+
end
|
423
|
+
Schema.execute
|
424
|
+
end
|
425
|
+
```
|
426
|
+
can be executed as follows (assuming your system can handle the shebang line or
|
427
|
+
has Ruby files associated with the ruby interpreter):
|
428
|
+
|
429
|
+
$ example-mapping.s2r example.xls
|
430
|
+
|
431
|
+
This call is equivalent to this:
|
432
|
+
|
433
|
+
$ spread2rdf -s example-mapping.s2r example.xls
|
434
|
+
|
435
|
+
### Compilation of mappings
|
436
|
+
An executable mapping can also be compiled to a Windows executable with the
|
437
|
+
```-c``` option of the ```spread2rdf``` command-line interface like this:
|
438
|
+
|
439
|
+
$ spread2rdf -c example-mapping.s2r
|
440
|
+
|
441
|
+
The resulting executable can then be used like the executable Ruby mapping file,
|
442
|
+
but without the need of an installed Ruby, since this is compiled into the
|
443
|
+
executable.
|
444
|
+
|
445
|
+
$ example-mapping.exe example.xls
|
446
|
+
|
447
|
+
## Contributing
|
448
|
+
|
449
|
+
1. Fork it
|
450
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
451
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
452
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
453
|
+
5. Create new Pull Request
|
454
|
+
|
26
455
|
## Author
|
27
456
|
|
28
457
|
* Marcel Otto
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.5
|
@@ -0,0 +1,334 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'spread2rdf'
|
3
|
+
|
4
|
+
module Spread2RDF
|
5
|
+
Schema.definition 'ProSysMod-Data' do
|
6
|
+
|
7
|
+
namespaces(
|
8
|
+
PSM: 'http://homepages.uni-paderborn.de/fbauer/ProSysMod/ontology#',
|
9
|
+
QUDT: 'http://qudt.org/schema/qudt#'
|
10
|
+
)
|
11
|
+
|
12
|
+
machine_classifications = %w[
|
13
|
+
PSM-Lagermittel-Klassifikation.ttl
|
14
|
+
PSM-Foerdermittel-Klassifikation.ttl
|
15
|
+
]
|
16
|
+
|
17
|
+
worksheet 'RDF-Export', name: :Settings do
|
18
|
+
NS[:Base] = cell(:B7)
|
19
|
+
NS[:PSM_MaterialElement] = cell(:B9)
|
20
|
+
NS[:PSM_Process] = cell(:B10)
|
21
|
+
NS[:PSM_Resource] = cell(:B11)
|
22
|
+
NS[:PSM_Characteristic] = cell(:B12)
|
23
|
+
NS[:PSM_Quality] = cell(:B13)
|
24
|
+
end
|
25
|
+
|
26
|
+
template :default_columns do
|
27
|
+
column :name, predicate: RDFS.label
|
28
|
+
column :uri
|
29
|
+
end
|
30
|
+
|
31
|
+
template :quantity_mapping do |value|
|
32
|
+
statements(
|
33
|
+
[ object, QUDT.numericValue, value.to_i ],
|
34
|
+
[ object, QUDT.unit, object_of_column(:unit) ] )
|
35
|
+
end
|
36
|
+
|
37
|
+
template :parameter_block do
|
38
|
+
column :name, predicate: PSM.characteristic,
|
39
|
+
object: { language: 'de',
|
40
|
+
from: {
|
41
|
+
worksheet: :Characteristics,
|
42
|
+
data_source: 'PSM-Merkmale.ttl' } }
|
43
|
+
#column :description, predicate: RDFS.comment
|
44
|
+
column :quality, predicate: PSM.parameterQuality,
|
45
|
+
object: { from: {
|
46
|
+
worksheet: :Qualities,
|
47
|
+
data_source: 'PSM-Qualitaeten.ttl' } }
|
48
|
+
column :min, predicate: PSM.parameterMinQuantity,
|
49
|
+
object: { uri: :bnode, type: QUDT.QuantityValue },
|
50
|
+
&quantity_mapping
|
51
|
+
column :exact, predicate: PSM.parameterQuantity,
|
52
|
+
object: { uri: :bnode, type: QUDT.QuantityValue },
|
53
|
+
&quantity_mapping
|
54
|
+
column :max, predicate: PSM.parameterMaxQuantity,
|
55
|
+
object: { uri: :bnode, type: QUDT.QuantityValue },
|
56
|
+
&quantity_mapping
|
57
|
+
column :unit, object: unit_mapping
|
58
|
+
column :valuation_method, predicate: PSM.usedByValuationMethod,
|
59
|
+
object: { from: :ValuationMethods }
|
60
|
+
end
|
61
|
+
|
62
|
+
worksheet 'Merkmale',
|
63
|
+
name: :Characteristics,
|
64
|
+
start: :B5,
|
65
|
+
subject: { uri: { namespace: PSM_Characteristic },
|
66
|
+
type: PSM.Characteristic
|
67
|
+
} do
|
68
|
+
column :name_de, predicate: RDFS.label, object: { language: 'de' }
|
69
|
+
column :name_en, predicate: RDFS.label, object: { language: 'en' }
|
70
|
+
column :uri
|
71
|
+
end
|
72
|
+
|
73
|
+
worksheet 'Qualitaeten',
|
74
|
+
name: :Qualities,
|
75
|
+
start: :B5,
|
76
|
+
subject: { uri: { namespace: PSM_Quality },
|
77
|
+
type: RDF::RDFS.Class,
|
78
|
+
#sub_class_of: PSM.Quality
|
79
|
+
} do
|
80
|
+
include :default_columns
|
81
|
+
column :elements, predicate: RDF.type, object: { uri: { namespace: PSM_Quality } },
|
82
|
+
statement: :inverse do |value|
|
83
|
+
statement( object, RDF::RDFS.label, value)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
worksheet 'Services',
|
88
|
+
start: :B5,
|
89
|
+
subject: { type: PSM.Service } do
|
90
|
+
include :default_columns
|
91
|
+
end
|
92
|
+
|
93
|
+
worksheet 'Bewertungsmethoden',
|
94
|
+
name: :ValuationMethods,
|
95
|
+
start: :B5,
|
96
|
+
subject: { type: PSM.ValuationMethod } do
|
97
|
+
include :default_columns
|
98
|
+
end
|
99
|
+
|
100
|
+
worksheet 'MaterialelementeKlassen',
|
101
|
+
name: :MaterialElementClasses,
|
102
|
+
start: :B5,
|
103
|
+
subject: { uri: { namespace: PSM_MaterialElement },
|
104
|
+
type: RDF::RDFS.Class,
|
105
|
+
sub_class_of: PSM.MaterialElement
|
106
|
+
} do
|
107
|
+
include :default_columns
|
108
|
+
|
109
|
+
column :sub_class_of, predicate: RDFS.subClassOf,
|
110
|
+
object: { from: :MaterialElementClasses }
|
111
|
+
column_block :parameter, subject: { uri: :bnode, type: PSM.Parameter },
|
112
|
+
predicate: PSM.materialParameter,
|
113
|
+
statement: :restriction,
|
114
|
+
¶meter_block
|
115
|
+
end
|
116
|
+
|
117
|
+
worksheet 'Materialelemente',
|
118
|
+
name: :MaterialElements,
|
119
|
+
start: :B5,
|
120
|
+
subject: { uri: { namespace: PSM_MaterialElement },
|
121
|
+
type: PSM.MaterialElement
|
122
|
+
} do
|
123
|
+
include :default_columns
|
124
|
+
|
125
|
+
column :type, predicate: RDF.type,
|
126
|
+
object: { from: :MaterialElementClasses }
|
127
|
+
column_block :parameter, subject: { uri: :bnode, type: PSM.Parameter },
|
128
|
+
predicate: PSM.materialParameter,
|
129
|
+
¶meter_block
|
130
|
+
end
|
131
|
+
|
132
|
+
worksheet 'ProzesseKlassen',
|
133
|
+
name: :ProcessClasses,
|
134
|
+
start: :B5,
|
135
|
+
subject: { uri: { namespace: PSM_Process },
|
136
|
+
type: RDF::RDFS.Class,
|
137
|
+
sub_class_of: PSM.Process
|
138
|
+
} do
|
139
|
+
include :default_columns
|
140
|
+
|
141
|
+
column :sub_class_of, predicate: RDFS.subClassOf,
|
142
|
+
object: { from: :ProcessClasses }
|
143
|
+
column :input, predicate: PSM.input,
|
144
|
+
object: { from: :MaterialElements },
|
145
|
+
statement: :restriction # TODO: Should we allow here Classes also, for which a subProperty with a restricted rdfs:range is introduced
|
146
|
+
column :output, predicate: PSM.ouput,
|
147
|
+
object: { from: :MaterialElements },
|
148
|
+
statement: :restriction # TODO: dto.
|
149
|
+
column_block :parameter, subject: { uri: :bnode, type: PSM.Parameter },
|
150
|
+
predicate: PSM.processParameter,
|
151
|
+
statement: :restriction,
|
152
|
+
¶meter_block
|
153
|
+
end
|
154
|
+
|
155
|
+
worksheet 'Prozesse',
|
156
|
+
name: :Processes,
|
157
|
+
start: :B5,
|
158
|
+
subject: { uri: { namespace: PSM_Process },
|
159
|
+
type: PSM.Process
|
160
|
+
} do
|
161
|
+
include :default_columns
|
162
|
+
|
163
|
+
column :type, predicate: RDF.type,
|
164
|
+
object: { from: :ProcessClasses }
|
165
|
+
column :input, predicate: PSM.input,
|
166
|
+
object: { from: :MaterialElements }
|
167
|
+
column :output, predicate: PSM.output,
|
168
|
+
object: { from: :MaterialElements }
|
169
|
+
column_block :parameter, subject: { uri: :bnode, type: PSM.Parameter },
|
170
|
+
predicate: PSM.processParameter,
|
171
|
+
¶meter_block
|
172
|
+
end
|
173
|
+
|
174
|
+
worksheet 'WerkzeugeKlassen',
|
175
|
+
name: :ToolClasses,
|
176
|
+
start: :B5,
|
177
|
+
subject: { uri: { namespace: PSM_Resource },
|
178
|
+
type: RDF::RDFS.Class,
|
179
|
+
sub_class_of: PSM.Tool
|
180
|
+
} do
|
181
|
+
include :default_columns
|
182
|
+
|
183
|
+
column :sub_class_of, predicate: RDFS.subClassOf,
|
184
|
+
object: { from: :ToolClasses }
|
185
|
+
column_block :parameter, subject: { uri: :bnode, type: PSM.Parameter },
|
186
|
+
predicate: PSM.resourceParameter,
|
187
|
+
statement: :restriction,
|
188
|
+
¶meter_block
|
189
|
+
end
|
190
|
+
|
191
|
+
worksheet 'Werkzeuge',
|
192
|
+
name: :Tools,
|
193
|
+
start: :B5,
|
194
|
+
subject: { uri: { namespace: PSM_Resource },
|
195
|
+
type: PSM.Tool
|
196
|
+
} do
|
197
|
+
include :default_columns
|
198
|
+
|
199
|
+
column :type, predicate: RDF.type,
|
200
|
+
object: { from: :ToolClasses }
|
201
|
+
column_block :parameter, subject: { uri: :bnode, type: PSM.Parameter },
|
202
|
+
predicate: PSM.resourceParameter,
|
203
|
+
¶meter_block
|
204
|
+
end
|
205
|
+
|
206
|
+
worksheet 'VorrichtungenKlassen',
|
207
|
+
name: :DeviceClasses,
|
208
|
+
start: :B5,
|
209
|
+
subject: { uri: { namespace: PSM_Resource },
|
210
|
+
type: RDF::RDFS.Class,
|
211
|
+
sub_class_of: PSM.Device
|
212
|
+
} do
|
213
|
+
include :default_columns
|
214
|
+
|
215
|
+
column :sub_class_of, predicate: RDFS.subClassOf,
|
216
|
+
object: { from: :DeviceClasses }
|
217
|
+
column_block :parameter, subject: { uri: :bnode, type: PSM.Parameter },
|
218
|
+
predicate: PSM.resourceParameter,
|
219
|
+
statement: :restriction,
|
220
|
+
¶meter_block
|
221
|
+
end
|
222
|
+
|
223
|
+
worksheet 'Vorrichtungen',
|
224
|
+
name: :Devices,
|
225
|
+
start: :B5,
|
226
|
+
subject: { uri: { namespace: PSM_Resource },
|
227
|
+
type: PSM.Device
|
228
|
+
} do
|
229
|
+
include :default_columns
|
230
|
+
|
231
|
+
column :type, predicate: RDF.type,
|
232
|
+
object: { from: :DeviceClasses }
|
233
|
+
column_block :parameter, subject: { uri: :bnode, type: PSM.Parameter },
|
234
|
+
predicate: PSM.resourceParameter,
|
235
|
+
¶meter_block
|
236
|
+
end
|
237
|
+
|
238
|
+
worksheet 'WerkerKlassen',
|
239
|
+
name: :WorkerClasses,
|
240
|
+
start: :B5,
|
241
|
+
subject: { uri: { namespace: PSM_Resource },
|
242
|
+
type: RDF::RDFS.Class,
|
243
|
+
sub_class_of: PSM.Worker
|
244
|
+
} do
|
245
|
+
include :default_columns
|
246
|
+
|
247
|
+
column :sub_class_of, predicate: RDFS.subClassOf,
|
248
|
+
object: { from: :WorkerClasses }
|
249
|
+
column :supported_services, predicate: PSM.supportsService,
|
250
|
+
object: { from: :Services },
|
251
|
+
statement: :restriction
|
252
|
+
column_block :parameter, subject: { uri: :bnode, type: PSM.Parameter },
|
253
|
+
predicate: PSM.resourceParameter,
|
254
|
+
statement: :restriction,
|
255
|
+
¶meter_block
|
256
|
+
end
|
257
|
+
|
258
|
+
worksheet 'Werker',
|
259
|
+
name: :Workers,
|
260
|
+
start: :B5,
|
261
|
+
subject: { uri: { namespace: PSM_Resource },
|
262
|
+
type: PSM.Worker
|
263
|
+
} do
|
264
|
+
include :default_columns
|
265
|
+
|
266
|
+
column :type, predicate: RDF.type,
|
267
|
+
object: { from: :WorkerClasses }
|
268
|
+
column :supported_services, predicate: PSM.supportsService,
|
269
|
+
object: { from: :Services }
|
270
|
+
column_block :parameter, subject: { uri: :bnode, type: PSM.Parameter },
|
271
|
+
predicate: PSM.resourceParameter,
|
272
|
+
¶meter_block
|
273
|
+
end
|
274
|
+
|
275
|
+
worksheet 'MaschinenKlassen',
|
276
|
+
name: :MachineClasses,
|
277
|
+
start: :B5,
|
278
|
+
subject: { uri: { namespace: PSM_Resource },
|
279
|
+
type: RDF::RDFS.Class,
|
280
|
+
sub_class_of: PSM.Machine
|
281
|
+
} do
|
282
|
+
include :default_columns
|
283
|
+
|
284
|
+
column :sub_class_of, predicate: RDFS.subClassOf,
|
285
|
+
object: { from: {
|
286
|
+
worksheet: :MachineClasses,
|
287
|
+
data_source: machine_classifications } }
|
288
|
+
|
289
|
+
column :tools # ignored
|
290
|
+
column :devices # ignored
|
291
|
+
column :workers # ignored
|
292
|
+
column :required_services, predicate: PSM.requiresService,
|
293
|
+
object: { from: :Services },
|
294
|
+
statement: :restriction
|
295
|
+
column :processes # ignored
|
296
|
+
|
297
|
+
column_block :parameter, subject: { uri: :bnode, type: PSM.Parameter },
|
298
|
+
predicate: PSM.resourceParameter,
|
299
|
+
statement: :restriction,
|
300
|
+
¶meter_block
|
301
|
+
end
|
302
|
+
|
303
|
+
worksheet 'Maschinen',
|
304
|
+
name: :Machines,
|
305
|
+
start: :B5,
|
306
|
+
subject: { uri: { namespace: PSM_Resource },
|
307
|
+
type: PSM.Machine
|
308
|
+
} do
|
309
|
+
include :default_columns
|
310
|
+
|
311
|
+
column :type, predicate: RDFS.subClassOf,
|
312
|
+
object: { from: {
|
313
|
+
worksheet: :MachineClasses,
|
314
|
+
data_source: machine_classifications } }
|
315
|
+
|
316
|
+
column :tools, predicate: PSM.hasTool,
|
317
|
+
object: { from: :Tools }
|
318
|
+
column :devices, predicate: PSM.hasDevice,
|
319
|
+
object: { from: :Devices }
|
320
|
+
column :workers, predicate: PSM.hasWorker,
|
321
|
+
object: { from: :Workers }
|
322
|
+
column :required_services, predicate: PSM.requiresService,
|
323
|
+
object: { from: :Services }
|
324
|
+
column :processes, predicate: PSM.realizeProcess,
|
325
|
+
object: { from: :Processes }
|
326
|
+
|
327
|
+
column_block :parameter, subject: { uri: :bnode, type: PSM.Parameter },
|
328
|
+
predicate: PSM.resourceParameter,
|
329
|
+
¶meter_block
|
330
|
+
end
|
331
|
+
|
332
|
+
end
|
333
|
+
Schema.execute
|
334
|
+
end
|
@@ -35,6 +35,8 @@ module Spread2RDF
|
|
35
35
|
value.blank?
|
36
36
|
end
|
37
37
|
|
38
|
+
private
|
39
|
+
|
38
40
|
def map_to_object(value)
|
39
41
|
case schema.object_mapping_mode
|
40
42
|
when :to_string then map_to_literal(value)
|
@@ -44,7 +46,6 @@ module Spread2RDF
|
|
44
46
|
else raise 'internal error: unknown column mapping mode'
|
45
47
|
end
|
46
48
|
end
|
47
|
-
private :map_to_object
|
48
49
|
|
49
50
|
def map_to_literal(value)
|
50
51
|
if language = schema.try(:object).try(:fetch, :language, nil)
|
@@ -53,7 +54,6 @@ module Spread2RDF
|
|
53
54
|
value
|
54
55
|
end
|
55
56
|
end
|
56
|
-
private :map_to_literal
|
57
57
|
|
58
58
|
def resolve_resource_ref
|
59
59
|
source = schema.object[:from]
|
@@ -65,7 +65,6 @@ module Spread2RDF
|
|
65
65
|
raise "#{self}: couldn't find a resource for #{value} in any of the defined sources"
|
66
66
|
end
|
67
67
|
end
|
68
|
-
private :resolve_resource_ref
|
69
68
|
|
70
69
|
def resolve_resource_ref_from_worksheet(worksheet_name)
|
71
70
|
worksheet = spreadsheet.worksheet(worksheet_name)
|
@@ -73,7 +72,6 @@ module Spread2RDF
|
|
73
72
|
source_predicate = RDF::RDFS.label # TODO: make this configurable via a attribute in the schema definition
|
74
73
|
query_subject(worksheet.graph, source_predicate, value, worksheet)
|
75
74
|
end
|
76
|
-
private :resolve_resource_ref_from_worksheet
|
77
75
|
|
78
76
|
def resolve_resource_ref_from_data_sources(data_sources)
|
79
77
|
raise ArgumentError, "expecting an Array, but got #{data_sources}" unless data_sources.is_a? Array
|
@@ -83,13 +81,11 @@ module Spread2RDF
|
|
83
81
|
end
|
84
82
|
nil
|
85
83
|
end
|
86
|
-
private :resolve_resource_ref_from_data_sources
|
87
84
|
|
88
85
|
def resolve_resource_ref_from_data_source(data_source)
|
89
86
|
source_predicate = RDF::RDFS.label # TODO: make this configurable via a attribute in the schema definition
|
90
87
|
query_subject(data_source, source_predicate, value)
|
91
88
|
end
|
92
|
-
private :resolve_resource_ref_from_data_source
|
93
89
|
|
94
90
|
def query_subject(data_source, predicate, value, data_source_name = nil)
|
95
91
|
data_source_name ||= "data source #{data_source}"
|
@@ -121,11 +117,12 @@ module Spread2RDF
|
|
121
117
|
#puts "executing block of #{@___column___} in row #{row}"
|
122
118
|
self.instance_exec(value, &block) if block_given?
|
123
119
|
end
|
124
|
-
private :exec
|
125
120
|
|
126
121
|
##########################################################################
|
127
122
|
# Element#_children_
|
128
123
|
|
124
|
+
public
|
125
|
+
|
129
126
|
def _children_
|
130
127
|
nil
|
131
128
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spread2rdf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marcel Otto
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-01
|
11
|
+
date: 2014-02-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -181,6 +181,7 @@ files:
|
|
181
181
|
- Rakefile
|
182
182
|
- VERSION
|
183
183
|
- bin/spread2rdf
|
184
|
+
- examples/ProSysMod.s2r.rb
|
184
185
|
- lib/spread2rdf.rb
|
185
186
|
- lib/spread2rdf/attributes.rb
|
186
187
|
- lib/spread2rdf/cli.rb
|