{"id":16746801,"url":"https://github.com/marcelotto/spread2rdf","last_synced_at":"2025-04-10T13:43:48.636Z","repository":{"id":11234399,"uuid":"13628326","full_name":"marcelotto/spread2rdf","owner":"marcelotto","description":"DSL-based converter for spreadsheets to RDF","archived":false,"fork":false,"pushed_at":"2014-02-27T00:22:52.000Z","size":400,"stargazers_count":4,"open_issues_count":5,"forks_count":2,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-08T21:24:42.222Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://rubygems.org/gems/spread2rdf","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/marcelotto.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-10-16T19:01:33.000Z","updated_at":"2023-08-05T08:00:42.000Z","dependencies_parsed_at":"2022-09-03T21:30:39.645Z","dependency_job_id":null,"html_url":"https://github.com/marcelotto/spread2rdf","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcelotto%2Fspread2rdf","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcelotto%2Fspread2rdf/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcelotto%2Fspread2rdf/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcelotto%2Fspread2rdf/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/marcelotto","download_url":"https://codeload.github.com/marcelotto/spread2rdf/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248226392,"owners_count":21068194,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-13T02:08:22.936Z","updated_at":"2025-04-10T13:43:48.611Z","avatar_url":"https://github.com/marcelotto.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Spread2RDF\n\nSpread2RDF is a converter for complex spreadsheets to RDF and a Ruby-internal\n[DSL](http://en.wikipedia.org/wiki/Domain-specific_language)\nfor specifying the mapping rules for this conversion.\n\n## Features\n\n* Supports Excel/Excelx, Google spreadsheets, OpenOffice, LibreOffice and CSV\n  spreadsheets as input, thanks to [Roo](https://github.com/Empact/roo).\n  (Currently, it's tested for Excel only.\n  If you have problems with other spreadsheet types,\n  [raise an issue](https://github.com/marcelotto/spread2rdf/issues).)\n* Supports many RDF serialization formats for the output, thanks to\n  [RDF.rb](https://github.com/ruby-rdf/rdf).\n* Mapping definitions can be compiled to executables, which are runnable without\n  having Ruby installed\n\n## Installation\n\nInstall [Ruby](http://www.ruby-lang.org/) and execute:\n\n    $ gem install spread2rdf\n\n## Command-line interface\n\nFor a full description of available parameters, run:\n\n    $ spread2rdf --help\n\n## How it works\n\nWrite a mapping file for the spreadsheet that should be converted to RDF.\nApply the mapping using the ```spread2rdf```\ncommand-line interface or a compiled version of the mapping file.\n\n### Example mapping file\n\n```ruby\nrequire 'spread2rdf'\n\nmodule Spread2RDF\n  Schema.definition 'ProSysMod-Data' do\n\n    namespaces(\n      PSM:    'http://example.com/ProSysMod/ontology#',\n      QUDT:   'http://qudt.org/schema/qudt#'\n    )\n\n    worksheet 'RDF-Export', name: :Settings do\n      NS[:Base]                = cell(:B7)\n      NS[:PSM_MaterialElement] = cell(:B9)\n    end\n\n    worksheet 'MaterialelementeKlassen',\n              name:    :MaterialElementClasses,\n              start:   :B5,\n              subject: { uri: { namespace: PSM_MaterialElement },\n                         type:         RDF::RDFS.Class,\n                         sub_class_of: PSM.MaterialElement\n              } do\n      column :name, predicate: RDFS.label\n      column :uri\n\n      column :sub_class_of,     predicate: RDFS.subClassOf,\n                                object:    { from: :MaterialElementClasses }\n      column_block :parameter,  subject: { uri: :bnode, type: PSM.Parameter },\n                                predicate: PSM.materialParameter,\n                                statement: :restriction do\n        column :name,        predicate: PSM.parameterName\n        column :description, predicate: PSM.parameterDescription\n\n        column :min,   predicate: PSM.parameterMinQuantity,\n                       object:    { uri: :bnode, type: QUDT.QuantityValue },\n                       \u0026quantity_mapping\n        column :exact, predicate: PSM.parameterQuantity,\n                       object:    { uri: :bnode, type: QUDT.QuantityValue },\n                       \u0026quantity_mapping\n        column :max,   predicate: PSM.parameterMaxQuantity,\n                       object:    { uri: :bnode, type: QUDT.QuantityValue },\n                       \u0026quantity_mapping\n        column :unit, object: lambda do |value|\n          statements(\n               [ object, QUDT.numericValue, value.to_i ],\n               [ object, QUDT.unit, object_of_column(:unit) ] )\n        end\n      end\n    end\n\n    worksheet 'Materialelemente',\n              name:   :MaterialElements,\n              start:  :B5,\n              subject: { uri: { namespace: PSM_MaterialElement },\n                         type: PSM.MaterialElement\n              } do\n      column :name, predicate: RDFS.label\n      column :uri\n\n      column :modified, predicate: DC.modified,\n                        object:    { datatype: XSD.date }\n\n      column :type, predicate: RDF.type,\n                    object:    { from: :MaterialElementClasses }\n\n      column_block :parameter,  subject: { uri: :bnode, type: PSM.Parameter },\n                                predicate: PSM.materialParameter do\n        column :name,        predicate: PSM.parameterName\n        column :description, predicate: PSM.parameterDescription\n\n        column :min,   predicate: PSM.parameterMinQuantity,\n                       object:    { uri: :bnode, type: QUDT.QuantityValue },\n                       \u0026quantity_mapping\n        column :exact, predicate: PSM.parameterQuantity,\n                       object:    { uri: :bnode, type: QUDT.QuantityValue },\n                       \u0026quantity_mapping\n        column :max,   predicate: PSM.parameterMaxQuantity,\n                       object:    { uri: :bnode, type: QUDT.QuantityValue },\n                       \u0026quantity_mapping\n        column :unit, object: lambda do |value|\n          statements(\n               [ object, QUDT.numericValue, value.to_i ],\n               [ object, QUDT.unit, object_of_column(:unit) ] )\n        end\n      end\n    end\n  end\nend\n```\n\nA complete example file, showcasing most of the features, can be found\n[in the examples directory](examples/ProSysMod.s2r.rb).\n\n### Mapping definition file\n\nA mapping file is a Ruby file containing a definition like this:\n\n```ruby\nrequire 'spread2rdf'\n\nmodule Spread2RDF\n  Schema.definition 'Name-of-the-mapping-schema' do\n\n  end\nend\n```\n\nThe name is purely descriptive and currently not used for anything else.\nThe definition block contains the description of your spreadsheets schema and\nthe conversion rules for mapping the cells to RDF.\n\n### URIs and namespaces\n\nURIs can be written in the form ```Namespace.suffix```, where the namespace is\nwritten in uppercase.\nThe most common namespaces like ```RDF, RDFS, OWL, SKOS, XSD, DC, FOAF``` (all\npredefined [RDF.rb vocabularies](http://rubydoc.info/github/ruby-rdf/rdf/master/RDF/Vocabulary))\nare available without prior declaration.\nAdditional namespaces can be defined statically using the ```namespace``` method\nin the schema definition block:\n```ruby\nmodule Spread2RDF\n  Schema.definition 'Name-of-the-mapping-schema' do\n    namespaces(\n      EX:   'http://www.example.com/',\n      QUDT: 'http://qudt.org/schema/qudt#'\n    )\n  end\nend\n```\nIf you want to declare a namespace dynamically, from the contents\nof a cell for example, an element can be added to the hash of namespaces\n```NS```. The name is given as a Ruby symbol:\n```ruby\nworksheet 'Settings' do\n  NS[:EX] = cell(:B7)\nend\n```\n\n### Worksheet schema definitions\nThe schema definition block should contain a worksheet definition for every\nworksheet to be processed.\nIt consists of\n- the keyword ```worksheet```,\n- followed by the name of the worksheet used in the spreadsheet as a string,\n- a list of named parameters (described below),\n- and a block with column or column block definitions or arbitrary cell\n  processing as in the ```Settings``` worksheet above.\nThe order of the worksheet definitions is not significant.\n\n###### ```name``` parameter\nIf you want to refer to a worksheet (e.g. in the ```subject``` parameter) with\na different name than the one used in the spreadsheet (because it contains\nwhitespaces for example), you can define it with this parameter.\n\n###### ```start``` parameter\nA Ruby symbol pointing to the upper-left cell of the data to be converted.\nAssuming the first row is a header (which is irrelevant for the conversion), the\ndefault value for this parameter is ```:A2```.\n\n###### ```subject``` parameter\nThis parameter specifies the construction of subject resources from rows.\nIt expects a hash with further sub-parameters as its value:\n- ```uri```: Defines the rules to construct an URI for the subject.\n  Possible values are:\n  - ```:bnode```: Construct a blank node for every subject.\n  - Another hash if a full URI should be constructed with the following possible\n    parameters:\n    - ```column```: The name of a column as a Ruby symbol, which contains the\n      base value for the construction of an URI for a subject.\n      In the following I will call this the subject column.\n      The default value for this is ```:uri```.\n    - ```namespace```: The namespace used to construct an URI for a subject by\n      concatenation with the corresponding value of the subject column.\n      If this is not specified, it is assumed that the subject column contains\n      absolute URIs.\n- ```type```: The URI of the RDFS class every subject should be an element of,\n  i.e. for every subject a ```rdf:type``` statement is produced with this URI as\n  its object.\n- ```sub_class_of```: The URI of a RDFS class every subject should be a\n  ```rdfs:subClassOf``` of,\n  i.e. for every subject a ```rdfs:subClassOf``` statement is produced with\n  this URI as its object.\n- ```column```: shortcut for the ```column``` sub-parameter of the ```uri``` parameter\n\nNote that the rows for a subject might span multiple rows of a worksheet, for\nexample when a column contains multiple rows with values for the same subject.\nThe range of rows for a subject is defined by the subject column according to\nthe following criteria:\n- The first row for a subject is the row with a non-empty value in the subject\n  column (by default the column ```:uri```).\n- The last row for a subject is the last row with an empty value in the subject\n  column or the last row of the worksheet.\n\n### Column schema definitions\nA column definition consists of\n- the keyword ```column```,\n- followed by a Ruby symbol with the arbitrary name of the column,\n- an optional list of named parameters (described below),\n- and an optional block with custom logic (described below).\nThe order of column definitions is significant and must correspond to the\norder of columns in the worksheet.\nFor columns which should be ignored, the parameters must be omitted.\nNote, that the first column is defined by the ```start``` parameter of the\nworksheet.\n\n###### ```predicate``` parameter\nThe URI of the RDF property which should be used for constructing of triples for\nvalues of this column.\nLeaving this parameter unspecified has the same effect as setting ```statement```\nto ```:none``` (see below).\n\n###### ```object``` parameter\nThis parameter specifies the construction of an object resource or value for a\nrow and expects a hash with further sub-parameters as its value:\n- ```language```:\n  A string or Ruby symbol with a language to be used to tag the object value of\n  the generated triple.\n- ```datatype```:\n  An URI to be used as the datatype for the object value of the generated triple.\n- ```uri```:\n  Specifies the rule for the generation of a resource for the object\n  of a triple. Currently, the following values are possible:\n  - ```:bnode```:\n    Generate a blank node. Primarily used in conjunction with the specification\n    of a Ruby block for custom logic (see below), where additional statements\n    about this object are generated.\n  - A Hash with a ```namespace``` key and a namespace as the value, which is\n    used to construct an URI by concatenating it with the corresponding cell\n    value of the column.\n- ```type```:\n  The URI of the RDFS class every object resource should be an element of, i.e.\n  for every object a ```rdf:type``` statement is produced with this URI as its\n  object.\n- ```from```:\n  Allows the specification of other data sources from which a resource is\n  referenced with a value of the column.\n  The graph of this data source is therefore queried for a resource with the\n  value of the column as its ```rdfs:label``` (currently this property is hard\n  coded, but could be made configurable).\n  The value of this parameter can be a Hash with one or a combination of the\n  following keys or a single Ruby symbol as a shortcut ```worksheet``` or a\n  single string or hash as a shortcut for ```data_source```.\n  - ```worksheet```: The name of a worksheet, whose generated output graph\n    should be queried.\n  - ```data_source```: A single filename or an array of filenames of RDF files,\n    which should be queried.\n    In case of relative paths the directory of the input spreadsheet and the\n    directories specified with the ```-I``` CLI parameter are used for the file\n    search.\n    Although not tested, also URLs to hosted RDF data should be possible instead\n    of filenames, due to RDF.rb.\nInstead of a hash with object construction parameter, it is also possible to\nspecify a Ruby proc with arbitrary object construction logic.\nThis block gets the value of a cell and should return the mapped value to be\nused as the object of the corresponding generated triple.\n\n###### ```statement``` parameter\nThis parameter allows the configuration of the triple generation.\nCurrently, the following values are possible:\n- ```:none```:\n  Don't generate a triple.\n  Useful in conjunction with Ruby blocks for custom logic.\n  Leaving the ```predicate``` parameter unspecified has the same effect.\n- ```:inverse```:\n  Use the subject resource (from the subject column) as the object and the\n  mapped value of a cell as the subject of the generated statement.\n- ```:restriction```:\n  This parameter value makes only sense, when the subject is a OWL class.\n  Instead of generating a triple of the form\n  ```subject predicate object .```,\n  where ```subject``` is the resource from the subject column,\n  ```predicate``` the value specified in the ```predicate``` parameter,\n  and ```object``` the mapped value from the cell of a column,\n  the following statements are generated:\n\n```\n  subject rdfs:subClassOf [\n    rdf:type owl:Restriction ;\n    owl:onProperty predicate ;\n    restriction_property object\n  ] .\n```\n\n  ```restriction_property``` is ```owl:hasValue``` by default, but can be\n  changed by giving a hash as the value of ```statement``` parameter, containing\n  ```:restriction``` as a key and the URI of restriction property as its value.\n\n###### Custom logic with Ruby blocks\nThe optional Ruby block can be used to generate further statements (or perform\ncustom actions in general) to the values of a column.\nThis block gets the cell value as an argument, but is executed in the context of\nthe [Cell class](lib/spread2rdf/mapping/cell.rb), so the mapped value can be\naccessed via the ```object``` method.\nIt's also possible to access the value or mapped value of another column of the\nsame row with the methods ```value_of_column``` or ```object_of_column```.\nA single statement can be generated with the ```statement``` method, which\nexpects three arguments for the subject, predicate and object.\nMultiple statements at once can be generated with the ```statements``` method,\nwhich takes an arbitrary number of array arguments containing the three subject,\npredicate and object elements of a triple.\n\n### Column block definitions\nA column block is used to define a sub sheet of a worksheet, meaning a series of\ncolumns (or further columns blocks) which are treated like a sheet, i.e.\nintroducing subject resources, which are used as the subject of the triples\ngenerated for these columns, while the subjects itself become objects of the\ntriples for the outer sheet (or column block).\n\nA column block definition consists of\n- the keyword ```column_block```,\n- followed by a Ruby symbol with an arbitrary name of the column block,\n- an optional list of named parameters,\n- and a Ruby block with column or further column block definitions.\nAll parameters of worksheets (except ```start```) and columns (the ```object```\nparameter) can be used as parameters of a column block definition.\n\n### Templates\nTemplates are a way to associate a name with a Ruby block in a worksheet,\nfor later reuse of definition blocks or mapping blocks.\nA template definition consists of\n- the keyword ```template```,\n- followed by a name as a Ruby symbol,\n- and a block.\nAfter a template definition the block can be accessed directly by using the defined\nname.\n\nExample:\n```ruby\nmodule Spread2RDF\n  Schema.definition 'Example' do\n    template :quantity_mapping do |value|\n      statements(\n          [ object, QUDT.numericValue, value.to_i ],\n          [ object, QUDT.unit, object_of_column(:unit) ] )\n    end\n\n    worksheet 'Example sheet' do\n      column :uri\n      column :value, predicate: PSM.parameterMaxQuantity,\n                     object:    { uri: :bnode, type: QUDT.QuantityValue },\n                     \u0026quantity_mapping\n      column :unit, object: unit_mapping # unit_mapping is a predefined custom object mapping to QUDT units\n    end\n  end\nend\n```\n\nAnother usage for templates is the definition of a sequence of columns in a worksheet\ndefinition, by calling the ```include``` method with the template name (in this case\nas Ruby symbol) in a worksheet definition (at the appropriate position).\n\nExample:\n```ruby\nmodule Spread2RDF\n  Schema.definition 'Example' do\n    template :default_columns do\n      column :name, predicate: RDFS.label\n      column :uri\n    end\n\n    worksheet 'Example sheet' do\n      include :default_columns\n    end\n  end\nend\n```\n\n## Executable mappings\nIt's possible to make a schema mapping definition executable as a command-line\napplication by placing a ```Schema.execute``` call after the schema definition\nin a mapping file.\nWith that, the mapping file can be used as an executable script file, which\nbehaves like ```spread2rdf``` with the schema mapping parameter ```-s```\nimplicitly set to this schema mapping, supporting all of its possible\nparameters  (except ```-s``` obviously).\n\nExample: A file ```example-mapping.s2r``` with the following definition\n```ruby\n#!/usr/bin/env ruby\n\nmodule Spread2RDF\n  Schema.definition 'Example' do\n    # ...\n  end\n  Schema.execute\nend\n```\ncan be executed as follows (assuming your system can handle the shebang line or\nhas Ruby files associated with the ruby interpreter):\n\n    $ example-mapping.s2r example.xls\n\nThis call is equivalent to this:\n\n    $ spread2rdf -s example-mapping.s2r example.xls\n\n### Compilation of mappings\nAn executable mapping can also be compiled to a Windows executable with the\n```-c``` option of the ```spread2rdf``` command-line interface like this:\n\n    $ spread2rdf -c example-mapping.s2r\n\nThe resulting executable can then be used like the executable Ruby mapping file,\nbut without the need of an installed Ruby, since this is compiled into the\nexecutable.\n\n    $ example-mapping.exe example.xls\n\n## Contributing\n\n1. Fork it\n2. Create your feature branch (`git checkout -b my-new-feature`)\n3. Commit your changes (`git commit -am 'Added some feature'`)\n4. Push to the branch (`git push origin my-new-feature`)\n5. Create new Pull Request\n\n## Author\n\n* Marcel Otto\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarcelotto%2Fspread2rdf","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmarcelotto%2Fspread2rdf","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarcelotto%2Fspread2rdf/lists"}