Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 20 additions & 5 deletions docs/datadoc/documenting-a-resource.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,21 +180,23 @@ Ex: `distribution.downloadURL`.

The header keyword(s) may be followed by an optional square bracket with the following syntax (inspired by URL options):

name[label?var1=value1&var2=value2]
name[label?key1=value1&key2=value2]

where
- `name`: is the column name that is mapped to a keyword (or set of dot-separated keywords) defined in the JSON-LD context.

- `name`: is the column name that is mapped to a keyword (or set of dot-separated keywords) defined in the JSON-LD context. (_required_)
The only formal requirement is that it cannot contain a begin brace ([), but it might be wise to be more strict.
- `label`: is a label for the column.
It is used to make the column unique or to group related columns.
The only formal requirement is that is cannot contain a question mark (?), but it is probably wise to be more strict.
The only formal requirement is that is cannot contain a question mark (?) or equal sign (=), but it is probably wise to be more strict.
A digit should be allowed.
- `key`: a key identifying an option for the column.
Should be a valid C or Python identifier (regex: `[_a-zA-Z][_a-zA-Z0-9]*`).
- `value`: the value of a key.
Should not contain (unescaped) ampersand (&) or end braces (]).

Currently recognised keys:

- **`unit`**: A unit symbol. All numbers in this column have this unit.
- **`sep`**: Separator character. A common user request when you have multiple values for a column, is to be able to provide multiple values in a single cell, instead of duplicating the column. This option makes it possible to specify a separator character that can be used in this column.

Expand All @@ -216,16 +218,29 @@ Grouping of columns (e.g. for DLite datamodels):

Specifying unit:

| @id | @type | length[?unit=m] |
| @id | @type | length[unit=m] |
|--------------|-------------|-----------------|
| ex:my_length | emmo:Length | 3.2 |

Specifying a separator:

| @id | @type | keyword[?sep=;] |
| @id | @type | keyword[sep=;] |
|-----------|--------------|--------------------|
| ex:mydata | emmo:Dataset | geology;stone;cave |

Combining label ('temsample') and unit ('unit=mm'):

| @id | @type | diameter[temsample?unit=mm] |
|-----------|--------------|-----------------------------|
| ex:mydata | emmo:Dataset | 3.0 |

Same as above, but with sample being a blank node (labeled 'temsample') with property `diameter` (with unit mm).
In this case, we put the label on the `hasSample` property and the unit on the `diameter` property:

| @id | @type | hasSample[temsample].diameter[unit=mm] |
|-----------|--------------|----------------------------------------|
| ex:mydata | emmo:Dataset | 3.0 |


### Complete example
For example, the table
Expand Down
13 changes: 9 additions & 4 deletions tests/datadoc/test_tabledoc.py
Original file line number Diff line number Diff line change
Expand Up @@ -388,12 +388,17 @@ def test_column():
assert col5.options == {"sep": ",", "unit": "m"}
assert col5.datatype is None

col6 = Column("creationDate", context=get_context())
assert col6.header == "creationDate"
assert col6.datatype == XSD.dateTime
col6 = Column("length[unit=m]")
assert col6.names == ["length"]
assert col6.label == ""
assert col6.options == {"unit": "m"}

col7 = Column("creationDate", context=get_context())
assert col7.header == "creationDate"
assert col7.datatype == XSD.dateTime

def test_sep():

def test_column_sep():
"""Test the column separation."""

from tripper.datadoc import TableDoc
Expand Down
14 changes: 11 additions & 3 deletions tripper/datadoc/tabledoc.py
Original file line number Diff line number Diff line change
Expand Up @@ -601,7 +601,7 @@ class Column:
# pylint: disable=too-few-public-methods

def __init__(self, header, context=None, strip=True):
# pylint: disable=line-too-long
# pylint: disable=line-too-long,too-many-branches
"""Initialise a column opject.

Arguments:
Expand All @@ -623,10 +623,18 @@ def __init__(self, header, context=None, strip=True):

label = fields[0][2].split("?", 1)[0]
spec = fields[-1][2].split("?", 1)
opts = spec[1] if len(spec) == 2 else ""

# Special rule. If `label` contains an equal sign (=), it is treated
# to be the first part of `opts`.
# This allows the user to omit the ?-sign if there is no label, e.g.
# writing "length[unit=m]" instead of "length[?unit=m]"
if "=" in label:
label, opts = "", f"{label}&{opts}" if opts else label

options = {}
if len(spec) == 2:
for opt in spec[1].split("&"):
if opts:
for opt in opts.split("&"):
k, v = opt.split("=", 1)
options[k] = v

Expand Down
Loading