Copyright © 2015 W3C ® ( MIT , ERCIM , Keio , Beihang ). W3C liability , trademark and document use rules apply.
This document defines the procedures and rules to be applied when converting tabular data into RDF. Tabular data may be complemented with metadata annotations that describe its structure, the meaning of its content and how it may form part of a collection of interrelated tabular data. This document specifies the effect of this metadata on the resulting RDF.
This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.w3.org/TR/.
The CSV on the Web Working Group was chartered to produce Recommendations for "Access methods for CSV Metadata", "Metadata vocabulary for CSV data" and "Mapping mechanism to transforming CSV into various Formats (e.g., RDF, JSON, or XML)". This document aims to satisfy the RDF variant of the mapping Recommendation.
This
document
was
published
by
the
CSV
on
the
Web
Working
Group
as
a
Working
Draft.
Candidate
Recommendation.
This
document
is
intended
to
become
a
W3C
Recommendation.
If
you
wish
to
make
comments
regarding
this
document,
please
send
them
to
public-csv-wg@w3.org
(
subscribe
,
archives
).
W3C
publishes
a
Candidate
Recommendation
to
indicate
that
the
document
is
believed
to
be
stable
and
to
encourage
implementation
by
the
developer
community.
This
Candidate
Recommendation
is
expected
to
advance
to
Proposed
Recommendation
no
earlier
than
30
October
2015.
All
comments
are
welcome.
Please see the Working Group's implementation report .
Publication
as
a
Working
Draft
Candidate
Recommendation
does
not
imply
endorsement
by
the
W3C
Membership.
This
is
a
draft
document
and
may
be
updated,
replaced
or
obsoleted
by
other
documents
at
any
time.
It
is
inappropriate
to
cite
this
document
as
other
than
work
in
progress.
This document was produced by a group operating under the 5 February 2004 W3C Patent Policy . W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy .
This document is governed by the 1 August 2014 W3C Process Document .
This document describes the processing of tabular data to create an RDF subject-predicate-object triples [ rdf11-concepts ]. Since RDF is an abstract syntax , these triples MAY be serialized in a concrete RDF syntax such as N-Triples [ n-triples ], Turtle [ turtle ], RDFa [ rdfa-primer ], JSON-LD [ json-ld ], or TriG [ trig ]. The RDF serializations offered by a conversion application is implementation defined.
The [ tabular-data-model ] defines an annotated tabular data model consisting of tables , columns , rows , and cells , enriched with annotations that describe the structure of the tabular data and the meaning of its content. A group of tables is a collection of tables published as a single atomic unit.
The conversion procedure described in this specification operates on the annotated tabular data model . This specification does not specify the processes needed to convert CSV-encoded data into tabular data form. Please refer to [ tabular-data-model ] for details of parsing tabular data .
Conversion applications MUST provide at least two modes of operation: standard and minimal .
Standard mode conversion frames the information gleaned from the cells of the tabular data with details of the rows , tables , and a group of tables within which that information is provided.
Minimal mode conversion includes only the information gleaned from the cells of the tabular data .
Standard and minimal conversion are described normatively below .
Conversion applications MAY offer additional implementation specific conversion modes.
Transformation definitions , as defined in [ tabular-metadata ] MAY be used to specify how tabular data can be transformed into another format using a script or template. Such transformation definitions MAY use the RDF output described in this specification as input.
There is no requirement on conversion applications to check the semantic consistency of the data during the conversion, nor to validate the triples against RDF schema. Downstream applications SHOULD be aware of the potential for inconsistencies and take appropriate action.
As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.
The key words MAY , MUST , and SHOULD are to be interpreted as described in [ RFC2119 ].
Tabular data MUST conform to the description from [ tabular-data-model ]. In particular note that each row MUST contain the same number of cells (although some of these cells may be empty).
Not all CSV-encoded data can be parsed into a tabular data model. An algorithm for parsing CSV-based files is described in [ tabular-data-model ].
This specification makes use of the compact IRI Syntax ; please refer to the Compact IRIs from [ json-ld ].
This specification makes use of the following namespaces:
csvw
:
http://www.w3.org/ns/csvw#
rdf
:
http://www.w3.org/1999/02/22-rdf-syntax-ns#
xsd
:
http://www.w3.org/2001/XMLSchema#
The following typographic conventions are used in this specification:
markup
markup
definition
reference
markup
external
definition
reference
Notes are in light green boxes with a green left border and with a "Note" header in green. Notes are normative or informative depending on the whether they are in a normative or informative section, respectively.
Examples are in light khaki boxes, with khaki left border, and with a numbered "Example" header in khaki. Examples are always informative. The content of the example is in monospace font and may be syntax colored.
The procedures for converting tabular data into RDF are described below for both standard and minimal modes.
null
or
a
sequence
of
values.
notes
property.
This
may
be
an
empty
list.
prefix
:
name
.
See
Names
of
Common
Properties
in
[
tabular-metadata
]
for
information
on
expansion.
null
.
A conformant RDF conversion application MUST emit triples conforming to those described in this algorithm according to the chosen mode of conversion: standard or minimal .
Unless specified otherwise, the steps in the algorithm defined herein apply to both standard and minimal modes.
Where an annotated table is defined in isolation (e.g. in the absence of a group of tables ), a default group of tables is provided with a single tables annotation that refers to the given table .
The [ tabular-data-model ] specifies that string values within tabular data (such as column titles or cell string values ) MUST contain only Unicode characters. No Unicode normalization (as specified in [ UAX15 ]) is applied to these string values during the conversion to RDF.
If a CSV file is originally encoded as UTF-8, it should not go through Unicode normalization during parsing, nor in conversion to RDF. This can result in RDF literals that are not in Normal Form C as they should be according to [ rdf11-concepts ].
null
,
then
node
G
MUST
be
a
new
blank
node
.
In
standard
mode
only,
specify
the
type
of
node
G
as
csvw:TableGroup
;
emit
the
following
triple:
rdf:type
csvw:TableGroup
In standard mode only, emit the triples generated by running the algorithm specified in section 6. JSON-LD to RDF over any notes and non-core annotations specified for the group of tables , with node G as an initial subject , the notes or non-core annotation as property , and the value of the notes or non-core annotation as value .
For
each
table
where
the
suppress
output
annotation
is
false
:
In standard mode only, establish a new node T which represents the current table .
If
the
table
has
an
identifier
then
node
T
MUST
be
identified
accordingly;
else
if
identifier
is
null
,
then
node
T
MUST
be
a
new
blank
node
.
In standard mode only, relate the table to the group of tables ; emit the following triple:
In
standard
mode
only,
specify
the
type
of
node
T
as
csvw:Table
;
emit
the
following
triple:
rdf:type
csvw:Table
In standard mode only, specify the source tabular data file URL for the current table based on the url annotation; emit the following triple:
In standard mode only, emit the triples generated by running the algorithm specified in section 6. JSON-LD to RDF over any notes and non-core annotations specified for the table , with node T as an initial subject , the notes or non-core annotation as property , and the value of the notes or non-core annotation as value .
All other core annotations for the table are ignored during the conversion; including information about table schemas and columns specified therein, foreign keys , table direction , transformations etc.
For each row in the current table :
In standard mode only, establish a new blank node R which represents the current row .
In standard mode only, relate the row to the table ; emit the following triple:
In
standard
mode
only,
specify
the
type
of
node
R
as
csvw:Row
;
emit
the
following
triple:
rdf:type
csvw:Row
In standard mode only, specify the row number n for the row ; emit the following triple:
csvw:rownum
xsd:integer
In
standard
mode
only,
specify
the
row
source
number
n
source
for
the
row
within
the
source
tabular
data
file
URL
using
a
fragment-identifier
as
specified
in
[
RFC7111
];
if
row
source
number
is
not
null
,
emit
the
following
triple:
In
standard
mode
only,
if
row
titles
is
not
null
,
insert
any
titles
specified
for
the
row
.
For
each
value,
t
v
,
of
the
row
titles
annotation,
emit
the
following
triple:
csvw:title
In standard mode only, emit the triples generated by running the algorithm specified in section 6. JSON-LD to RDF over any non-core annotations specified for the row , with node R as an initial subject , the non-core annotation as property , and the value of the non-core annotation as value .
Establish a new blank node S def to be used as the default subject for cells where about URL is undefined.
A row MAY describe multiple interrelated subjects ; where the value URL annotation on one cell matches the about URL annotation on another cell in the same row .
For
each
cell
in
the
current
row
where
the
suppress
output
annotation
for
the
column
associated
with
that
cell
is
false
:
Establish a node S from about URL if set, or from S def otherwise as the current subject .
In standard mode only, relate the current subject to the current row ; emit the following triple:
If
the
value
of
property
URL
for
the
cell
is
not
null
,
then
predicate
P
takes
the
value
of
property
URL
.
Else, predicate P is constructed by appending the value of the name annotation for the column associated with the cell to the the tabular data file URL as a fragment identifier.
null
,
then
value
URL
identifies
a
node
V
url
that
is
related
the
current
subject
using
the
predicate
P
;
emit
the
following
triple:
true
,
then
the
cell
value
provides
an
ordered
sequence
of
literal
nodes
for
inclusion
within
the
RDF
output
using
an
instance
of
rdf:List
V
list
as
defined
in
[
rdf-schema
].
This
instance
is
related
to
the
subject
using
the
predicate
P
;
emit
the
triples
defining
list
V
list
plus
the
following
triple:
null
,
then
the
cell
value
provides
a
single
literal
node
V
literal
for
inclusion
within
the
RDF
output
that
is
related
the
current
subject
using
the
predicate
P
;
emit
the
following
triple:
The literal nodes derived from the cell values MUST be expressed according to the cell value's datatype as defined below: Interpreting datatypes .
In
the
case
when
a
cell
value
does
not
have
a
datatype
,
the
conversion
should
default
to
string
.
In the case where a sequence of values is provided, each value in the list has its own datatype ; the datatype may be different for different items in the sequence.
Cell
values
are
expressed
in
the
RDF
output
according
to
the
cell
value's
datatype
.
The
relationship
between
the
value
of
the
cell
value's
datatype
and
the
datatype
IRI
used
in
the
RDF
output
is
provided
in
as
follows:
null
,
then
its
value
MUST
be
used
as
the
RDF
datatype
IRI
;
A datatype's format annotation is irrelevant to the conversion procedure defined in this specification; the cell value has already been parsed from the contents the cell according to the format annotation.
Where the contents of the cell cannot be parsed, or other validation errors occur, cell errors will be provided. It is an implementation decision to determine how conversion applications should proceed in the event that cell errors are encountered.
datatype
|
RDF datatype IRI | Remarks |
---|---|---|
anyAtomicType
|
xsd:anyAtomicType
|
|
anyURI
|
xsd:anyURI
|
|
base64Binary
|
xsd:base64Binary
|
|
boolean
|
xsd:boolean
|
|
date
|
xsd:date
|
|
dateTime
|
xsd:dateTime
|
|
dateTimeStamp
|
xsd:dateTimeStamp
|
|
decimal
|
xsd:decimal
|
|
integer
|
xsd:integer
|
|
long
|
xsd:long
|
|
int
|
xsd:int
|
|
short
|
xsd:short
|
|
byte
|
xsd:byte
|
|
nonNegativeInteger
|
xsd:nonNegativeInteger
|
|
positiveInteger
|
xsd:positiveInteger
|
|
unsignedLong
|
xsd:unsignedLong
|
|
unsignedInt
|
xsd:unsignedInt
|
|
unsignedShort
|
xsd:unsignedShort
|
|
unsignedByte
|
xsd:unsignedByte
|
|
nonPositiveInteger
|
xsd:nonPositiveInteger
|
|
negativeInteger
|
xsd:negativeInteger
|
|
double
|
xsd:double
|
|
duration
|
xsd:duration
|
|
dayTimeDuration
|
xsd:dayTimeDuration
|
|
yearMonthDuration
|
xsd:yearMonthDuration
|
|
float
|
xsd:float
|
|
gDay
|
xsd:gDay
|
|
gMonth
|
xsd:gMonth
|
|
gMonthDay
|
xsd:gMonthDay
|
|
gYear
|
xsd:gYear
|
|
gYearMonth
|
xsd:gYearMonth
|
|
hexBinary
|
xsd:hexBinary
|
|
QName
|
xsd:QName
|
|
string
|
xsd:string
or
rdf:langString
depending
on
whether
or
not
the
value
has
an
associated
language.
|
|
normalizedString
|
xsd:normalizedString
|
|
token
|
xsd:token
|
|
language
|
xsd:language
|
|
Name
|
xsd:Name
|
|
NMTOKEN
|
xsd:NMTOKEN
|
|
xml
|
rdf:XMLLiteral
|
|
html
|
rdf:HTML
|
|
json
|
csvw:JSON
|
csvw:JSON
is
a
sub-class
of
xsd:string
|
time
|
xsd:time
|
In
the
case
of
rdf:langString
,
the
appropriate
language
tag
(as
defined
in
[
rdf11-concepts
])
MUST
be
provided
for
the
string,
based
on
the
value
of
cell
value's
language
.
(See
section
on
Graph
Literals
in
[
rdf11-concepts
]
for
further
details
on
language
tagged
literals.)
According
to
[
rdf11-concepts
]
language
tags
cannot
be
combined
with
any
other
xsd
datatypes.
If
a
cell
has
any
other
datatype
than
string
,
the
value
of
lang
MUST
be
ignored.
Also,
all
literals
have
a
datatype;
however,
specific
serializations,
like
Turtle
[
turtle
],
MAY
provide
a
special
syntax
for
literals
with
datatype
xsd:string
or
rdf:langString
.
This section is non-normative.
In addition to the namespaces defined above , the following namespace is used in this section:
prov
:
http://www.w3.org/ns/prov#
Conversion applications MAY include provenance information in the RDF output describing how and when the output was created; e.g., using terms from the PROV Ontology [ prov-o ]. Information that may be of interest to downstream applications includes:
In
order
to
faciliate
the
provision
of
such
information,
this
specification
introduces
two
instances
of
prov:Role
:
csvw:csvEncodedTabularData
csvw:tabularMetadata
http://example.org/my-csv2rdf-application
:
@prefix csvw: <http://www.w3.org/ns/csvw#> . @prefix prov: <http://www.w3.org/ns/prov#> . @prefix xsd: <http://www.w3.org/2001/XMLSchema#> . <> prov:wasGeneratedBy [ a prov:Activity ; prov:wasAssociatedWith <http://example.org/my-csv2rdf-application> ; prov:startedAtTime "2015-02-13T15:12:44"^^xsd:dateTime ; prov:endedAtTime "2015-02-13T15:12:46"^^xsd:dateTime ; prov:qualifiedUsage [ a prov:Usage ; prov:entity <http://example.org/csv/data.csv> ; prov:hadRole csvw:csvEncodedTabularData ]; prov:qualifiedUsage [ a prov:Usage ; prov:entity <http://example.org/csv/data.csv-metadata.json> ,<http://example.org/csv/csv-metadata.json> ; prov:hadRole csvw:tabularMetadata ]; ]
This section defines a mechanism for transforming the [ json-ld ] dialect used for non-core annotations and notes originating from the processing of metadata (as defined in [ tabular-metadata ]) into RDF in a manner consistent with the Deserialize JSON-LD to RDF Algorithm defined in [ json-ld-api ]. Converters MAY use any algorithm which results in equivalent triples.
Conversion applications may have other means to create annotated tables , e.g., through some application specific API-s. In such cases the exact format for non-core annotations or notes may be different. Specifications for such annotation processes should specify how these annotations should be converted into RDF.
Given a subject , property and value in normalized form:
@value
,
create
an
RDF
Literal
lit
using
the
string
value
of
@value
and
language
from
@language
,
or
datatype
from
@type
if
present,
expanding
@type
as
necessary
using
the
procedure
outlined
for
property
,
and
emit
the
following
triple:
If
neither
@language
nor
@type
is
present,
the
literal
lit
has
the
datatype
xsd:string
.
@id
,
if
it
exists,
and
new
blank
node
otherwise
and
emit
the
following
triple:
@type
,
either
a
term
defined
in
the
[
csvw-context
],
a
prefixed
name
,
or
an
absolute
URL;
establish
a
new
node
T
i
by
expanding
the
value
to
an
absolute
URL
by
replacing
a
term
with
the
URI
from
the
term
definition
in
[
csvw-context
]
or
a
prefixed
name
with
its
expanded
value.
For
each
T
i
,
emit
the
following
triple:
@
(
U+0040
)
generate
RDF
by
running
this
algorithm
using
S
for
subject
,
key
for
property
and
val
for
value
.
true
or
false
,
create
an
RDF
Literal
lit
using
the
strings
"true"
or
"false",
accordingly
with
datatype
xsd:boolean
xsd:double
.
xsd:integer
.
xsd:string
.
Emit the following triple:
This section is non-normative.
In addition to the namespaces defined above , the examples provided here make use of the following namespaces:
dc
:
http://purl.org/dc/terms/
foaf
:
http://xmlns.com/foaf/0.1/
oa
:
http://www.w3.org/ns/oa#
org
:
http://www.w3.org/ns/org#
schema
:
http://schema.org/
Furthermore,
these
examples
also
make
use
of
the
Turtle
syntax
@base
declaration
(as
defined
in
[
turtle
]).
Where
a
single
tabular
data
file
is
used
in
the
example,
the
@base
declaration
is
set
to
the
URL
of
that
tabular
data
file.
Each of the examples expresses more complex conversions - it is recommended that readers of this specification work through the examples in sequential order.
This
example
comprises
a
single
annotated
table
containing
information
attributes
about
countries;
country
code,
position
(latitude,
longitude)
and
name.
Whilst
the
input
tabular
data
file,
published
at
http://example.org/countries.csv
,
includes
a
header
line
,
no
further
metadata
annotations
are
given.
The
tabular
data
file
is
provided
below:
countryCode,latitude,longitude,nameAD,42.546245,1.601554,Andorra AE,23.424076,53.847818,"United Arab Emirates" AF,33.93911,67.709953,AfghanistanAD,42.5,1.6,Andorra AE,23.4,53.8,"United Arab Emirates" AF,33.9,67.7,Afghanistan
The annotated table generated from parsing the tabular data file is shown below and provides the basis for the conversion to RDF.
Annotations for the resulting table T , with 4 columns and 3 rows, are shown below:
id | core annotations | ||
---|---|---|---|
url | columns | rows | |
T |
http://example.org/countries.csv
|
C1 , C2 , C3 , C4 | R1 , R2 , R3 |
Annotations for the columns , rows and cells in table T are shown in the tables below.
Column annotations:
id | core annotations | |||||
---|---|---|---|---|---|---|
table | number | source number | cells | name | titles | |
C1 | T | 1 | 1 | C1.1 , C2.1 , C3.1 |
countryCode
|
countryCode
|
C2 | T | 2 | 2 | C1.2 , C2.2 , C3.2 |
latitude
|
latitude
|
C3 | T | 3 | 3 | C1.3 , C2.3 , C3.3 |
longitude
|
longitude
|
C4 | T | 4 | 4 | C1.4 , C2.4 , C3.4 |
name
|
name
|
Row annotations:
id | core annotations | |||
---|---|---|---|---|
table | number | source number | cells | |
R1 | T | 1 | 2 | C1.1 , C1.2 , C1.3 , C1.4 |
R2 | T | 2 | 3 | C2.1 , C2.2 , C2.3 , C2.4 |
R3 | T | 3 | 4 | C3.1 , C3.2 , C3.3 , C3.4 |
Cell annotations:
id | core annotations | |||||
---|---|---|---|---|---|---|
table | column | row | string value | value | property URL | |
C1.1 | T | C1 | R1 |
"AD"
|
"AD"
|
null
|
C1.2 | T | C2 | R1 |
|
|
null
|
C1.3 | T | C3 | R1 |
|
|
null
|
C1.4 | T | C4 | R1 |
"Andorra"
|
"Andorra"
|
null
|
C2.1 | T | C1 | R2 |
"AE"
|
"AE"
|
null
|
C2.2 | T | C2 | R2 |
|
|
null
|
C2.3 | T | C3 | R2 |
|
|
null
|
C2.4 | T | C4 | R2 |
"United
Arab
Emirates"
|
"United
Arab
Emirates"
|
null
|
C3.1 | T | C1 | R3 |
"AF"
|
"AF"
|
null
|
C3.2 | T | C2 | R3 |
|
|
null
|
C3.3 | T | C3 | R3 |
|
|
null
|
C3.4 | T | C4 | R3 |
"Afghanistan"
|
"Afghanistan"
|
null
|
Minimal mode output for this example is provided in Turtle [ turtle ] syntax below:
@base <http://example.org/countries.csv> . _:8228a149-8efe-448d-b15f-8abf92e7bd17 <#countryCode> "AD" ;<#latitude> "42.5" ; <#longitude> "1.6" ; <#name> "Andorra" . _:ec59dcfc-872a-4144-822b-9ad5e2c6149c <#countryCode> "AE" ;<#latitude> "23.4" ; <#longitude> "53.8" ; <#name> "United Arab Emirates" . _:e8f2e8e9-3d02-4bf5-b4f1-4794ba5b52c9 <#countryCode> "AF" ;<#latitude> "33.9" ; <#longitude> "67.7" ; <# name > "Afghanistan" .
The
about
URL
annotation
has
not
been
set
for
cells
in
table
T
(
{
"url":
"http://example.org/countries.csv"}
);
cells
in
a
given
row
where
about
URL
has
not
been
specified
are
assumed
to
refer
to
the
same
subject
.
This
unspecified
subject
is
treated
as
a
blank
node
.
Given
that
the
property
URL
is
null
for
cells
in
table
T
(
{
"url":
"http://example.org/countries.csv"}
),
the
property
URL
defaults
to
the
URI
Template
(see
[
RFC6570
])
#{
[column-name]
}
,
where
[column-name]
is
the
value
of
the
name
annotation
of
the
column
associated
with
the
cell.
For
example,
the
value
of
the
property
URL
annotation
for
all
cells
in
column
C1
(
"name":
"countryCode"
)
is
http://example.org/countries.csv#countryCode
.
Standard mode output for this example is provided in Turtle [ turtle ] syntax below:
@base <http://example.org/countries.csv> . @prefix csvw: <http://www.w3.org/ns/csvw#> . @prefix xsd: <http://www.w3.org/2001/XMLSchema#> . _:d4f8e548-9601-4e41-aadb-09a8bce32625 a csvw:TableGroup ; csvw:table [ a csvw:Table ; csvw:url <http://example.org/countries.csv> ; csvw:row [ a csvw:Row ; csvw:rownum "1"^^xsd:integer ; csvw:url <#row=2> ; csvw:describes _:8228a149-8efe-448d-b15f-8abf92e7bd17 ], [ a csvw:Row ; csvw:rownum "2"^^xsd:integer ; csvw:url <#row=3> ; csvw:describes _:ec59dcfc-872a-4144-822b-9ad5e2c6149c ], [ a csvw:Row ; csvw:rownum "3"^^xsd:integer ; csvw:url <#row=4> ; csvw:describes _:e8f2e8e9-3d02-4bf5-b4f1-4794ba5b52c9 ] ] . _:8228a149-8efe-448d-b15f-8abf92e7bd17 <#countryCode> "AD" ;<#latitude> "42.5" ; <#longitude> "1.6" ; <#name> "Andorra" . _:ec59dcfc-872a-4144-822b-9ad5e2c6149c <#countryCode> "AE" ;<#latitude> "23.4" ; <#longitude> "53.8" ; <#name> "United Arab Emirates" . _:e8f2e8e9-3d02-4bf5-b4f1-4794ba5b52c9 <#countryCode> "AF" ;<#latitude> "33.9" ; <#longitude> "67.7" ; <# name > "Afghanistan" .
Even though the table was defined in isolation, the annotated table is wrapped in a group of tables .
The
type
of
both
table
and
group
of
tables
objects
is
explicitly
stated;
csvw:TableGroup
and
csvw:Table
respectively.
The
csvw:url
property
provides
reference
to
the
original
tabular
data
file
and
to
specific
rows
therein
-
noting
the
need
to
escape
the
Turtle-syntax
reserved
character
=
(
U+003D
)
within
the
fragment
identifier.
The
row
number
is
provided
for
each
row
using
csvw:rownum
property.
A
subject
and
row
are
related
using
the
csvw:describes
property.
This
example
is
based
on
Use
Case
#11
-
City
of
Palo
Alto
Tree
Data
and
comprises
a
single
annotated
table
describing
an
inventory
of
tree
maintenance
operations.
The
input
tabular
data
file,
published
at
http://example.org/tree-ops-ext.csv
,
and
the
associated
metadata
description
http://example.org/tree-ops-ext.csv-metadata.json
are
provided
below:
GID,On Street,Species,Trim Cycle,Diameter at Breast Ht,Inventory Date,Comments,Protected,KML 1,ADDISON AV,Celtis australis,Large Tree Routine Prune,11,10/18/2010,,,"<Point><coordinates>-122.156485,37.440963</coordinates></Point>" 2,EMERSON ST,Liquidambar styraciflua,Large Tree Routine Prune,11,6/2/2010,,,"<Point><coordinates>-122.156749,37.440958</coordinates></Point>" 6,ADDISON AV,Robinia pseudoacacia,Large Tree Routine Prune,29,6/1/2010,cavity or decay; trunk decay; codominant leaders; included bark; large leader or limb decay; previous failure root damage; root decay; beware of BEES,YES,"<Point><coordinates>-122.156299,37.441151</coordinates></Point>"
{ "@context": ["http://www.w3.org/ns/csvw", {"@language": "en"}], "@id": "http://example.org/tree-ops-ext", "url": "tree-ops-ext.csv", "dc:title": "Tree Operations", "dcat:keyword": ["tree", "street", "maintenance"], "dc:publisher": [{ "schema:name": "Example Municipality", "schema:url": {"@id": "http://example.org"} }], "dc:license": {"@id": "http://opendefinition.org/licenses/cc-by/"}, "dc:modified": {"@value": "2010-12-31", "@type": "xsd:date"}, "notes": [{ "@type": "oa:Annotation", "oa:hasTarget": {"@id": "http://example.org/tree-ops-ext"}, "oa:hasBody": { "@type": "oa:EmbeddedContent", "rdf:value": "This is a very interesting comment about the table; it's a table!", "dc:format": {"@value": "text/plain"} } }], "dialect": {"trim": true}, "tableSchema": { "columns": [{ "name": "GID", "titles": [ "GID", "Generic Identifier" ], "dc:description": "An identifier for the operation on a tree.", "datatype": "string", "required": true, "suppressOutput": true }, { "name": "on_street", "titles": "On Street", "dc:description": "The street that the tree is on.", "datatype": "string" }, { "name": "species", "titles": "Species", "dc:description": "The species of the tree.", "datatype": "string" }, { "name": "trim_cycle", "titles": "Trim Cycle", "dc:description": "The operation performed on the tree.", "datatype": "string", "lang": "en" }, { "name": "dbh", "titles": "Diameter at Breast Ht", "dc:description": "Diameter at Breast Height (DBH) of the tree (in feet), measured 4.5ft above ground.", "datatype": "integer" }, { "name": "inventory_date", "titles": "Inventory Date", "dc:description": "The date of the operation that was performed.", "datatype": {"base": "date", "format": "M/d/yyyy"} }, { "name": "comments", "titles": "Comments", "dc:description": "Supplementary comments relating to the operation or tree.", "datatype": "string", "separator": ";" }, { "name": "protected", "titles": "Protected", "dc:description": "Indication (YES / NO) whether the tree is subject to a protection order.", "datatype": {"base": "boolean", "format": "YES|NO"}, "default": "NO" }, { "name": "kml", "titles": "KML", "dc:description": "KML-encoded description of tree location.", "datatype": "xml" }], "primaryKey": "GID", "aboutUrl": "http://example.org/tree-ops-ext#gid-{GID}" } }
The notes annotation in the metadata description uses the Open Annotation data model currently under development within the Web Annotations Working Group . This is purely illustrative; no constraints are placed on the value of the notes annotation.
The annotated table generated from parsing the tabular data file and associated metadata is shown below and provides the basis for the conversion to RDF.
Core annotations for the resulting table T , with 9 columns and 3 rows , are shown below:
id | core annotations | ||||
---|---|---|---|---|---|
id | url | columns | rows | notes | |
T | <http://example.org/tree-ops-ext> |
http://example.org/tree-ops-ext.csv
|
C1 , C2 , C3 , C4 , C5 , C6 , C7 , C8 , C9 | R1 , R2 , R3 |
[{
"@type":
"oa:Annotation",
...
}]
|
Non-core annotations for the table T are:
dc:title
"Tree
Operations"
dcat:keyword
["tree",
"street",
"maintenance"]
dc:publisher
[{
"schema:name":
"Example
Municipality",
"schema:url":
{
"@id":
"http://example.org"
}
}]
dc:license
{
"@id":
"http://opendefinition.org/licenses/cc-by/"
}
dc:modified
"2010-12-31"
The value of the notes annotation has been shortened for clarity in the table above.
Annotations for the columns , rows and cells in table T are shown in the tables below.
Column annotations:
id | core annotations | annotations | |||||||
---|---|---|---|---|---|---|---|---|---|
table | number | source number | cells | name | titles | required | suppress output |
dc:description
|
|
C1 | T | 1 | 1 | C1.1 , C2.1 , C3.1 |
GID
|
GID
,
Generic
Identifier
|
true
|
true
|
An
identifier
for
the
operation
on
a
tree.
|
C2 | T | 2 | 2 | C1.2 , C2.2 , C3.2 |
on_street
|
On
Street
|
The
street
that
the
tree
is
on.
|
||
C3 | T | 3 | 3 | C1.3 , C2.3 , C3.3 |
species
|
Species
|
The
species
of
the
tree.
|
||
C4 | T | 4 | 4 | C1.4 , C2.4 , C3.4 |
trim_cycle
|
Trim
Cycle
|
The
operation
performed
on
the
tree.
|
||
C5 | T | 5 | 5 | C1.5 , C2.5 , C3.5 |
dbh
|
Diameter
at
Breast
Ht
|
Diameter
at
Breast
Height
(DBH)
of
the
tree
(in
feet),
measured
4.5ft
above
ground.
|
||
C6 | T | 6 | 6 | C1.6 , C2.6 , C3.6 |
inventory_date
|
Inventory
Date
|
The
date
of
the
operation
that
was
performed.
|
||
C7 | T | 7 | 7 | C1.7 , C2.7 , C3.7 |
comments
|
Comments
|
Supplementary
comments
relating
to
the
operation
or
tree.
|
||
C8 | T | 8 | 8 | C1.8 , C2.8 , C3.8 |
protected
|
Protected
|
Indication
(YES
/
NO)
whether
the
tree
is
subject
to
a
protection
order.
|
||
C9 | T | 9 | 9 | C1.9 , C2.9 , C3.9 |
kml
|
KML
|
KML-encoded
description
of
tree
location.
|
In
this
example,
output
for
column
C1
(
GID
)
is
not
required;
note
the
suppress
output
annotation
on
this
column
.
Row annotations:
id | core annotations | ||||
---|---|---|---|---|---|
table | number | source number | cells | primary key | |
R1 | T | 1 | 2 | C1.1 , C1.2 , C1.3 , C1.4 , C1.5 , C1.6 , C1.7 , C1.8 , C1.9 | C1.1 |
R2 | T | 2 | 3 | C2.1 , C2.2 , C2.3 , C2.4 , C2.5 , C2.6 , C2.7 , C2.8 , C2.9 | C2.1 |
R3 | T | 3 | 4 | C3.1 , C3.2 , C3.3 , C3.4 , C3.5 , C3.6 , C3.7 , C3.8 , C3.9 | C3.1 |
Cell annotations:
id | core annotations | |||||
---|---|---|---|---|---|---|
table | column | row | string value | value | about URL | |
C1.1 | T | C1 | R1 |
"1"
|
"1"
|
http://example.org/tree-ops-ext#gid-1
|
C1.2 | T | C2 | R1 |
"ADDISON
AV"
|
"ADDISON
AV"
|
<http://example.org/tree-ops-ext#gid-1>
|
C1.3 | T | C3 | R1 |
"Celtis
australis"
|
"Celtis
australis"
|
<http://example.org/tree-ops-ext#gid-1>
|
C1.4 | T | C4 | R1 |
"Large
Tree
Routine
Prune"
|
"Large
Tree
Routine
Prune"
(English)
|
<http://example.org/tree-ops-ext#gid-1>
|
C1.5 | T | C5 | R1 |
"11"
|
11
|
<http://example.org/tree-ops-ext#gid-1>
|
C1.6 | T | C6 | R1 |
"10/18/2010"
|
2010-10-18
|
<http://example.org/tree-ops-ext#gid-1>
|
C1.7 | T | C7 | R1 |
""
|
null
|
<http://example.org/tree-ops-ext#gid-1>
|
C1.8 | T | C8 | R1 |
""
|
false
|
<http://example.org/tree-ops-ext#gid-1>
|
C1.9 | T | C9 | R1 |
"<Point><coordinates>-122.156485,37.440963</coordinates></Point>"
|
"<Point><coordinates>-122.156485,37.440963</coordinates></Point>"
(XML)
|
<http://example.org/tree-ops-ext#gid-1>
|
C2.1 | T | C1 | R2 |
"2"
|
"2"
|
<http://example.org/tree-ops-ext#gid-2>
|
C2.2 | T | C2 | R2 |
"EMERSON
ST"
|
"EMERSON
ST"
|
<http://example.org/tree-ops-ext#gid-2>
|
C2.3 | T | C3 | R2 |
"Liquidambar
styraciflua"
|
"Liquidambar
styraciflua"
|
<http://example.org/tree-ops-ext#gid-2>
|
C2.4 | T | C4 | R2 |
"Large
Tree
Routine
Prune"
|
"Large
Tree
Routine
Prune"
(English)
|
<http://example.org/tree-ops-ext#gid-2>
|
C2.5 | T | C5 | R2 |
"11"
|
11
|
<http://example.org/tree-ops-ext#gid-2>
|
C2.6 | T | C6 | R2 |
"6/2/2010"
|
2010-06-02
|
<http://example.org/tree-ops-ext#gid-2>
|
C2.7 | T | C7 | R2 |
""
|
null
|
<http://example.org/tree-ops-ext#gid-2>
|
C2.8 | T | C8 | R2 |
""
|
false
|
<http://example.org/tree-ops-ext#gid-2>
|
C2.9 | T | C9 | R2 |
"<Point><coordinates>-122.156749,37.440958</coordinates></Point>"
|
"<Point><coordinates>-122.156749,37.440958</coordinates></Point>"
(XML)
|
<http://example.org/tree-ops-ext#gid-2>
|
C3.1 | T | C1 | R3 |
"6"
|
"6"
|
<http://example.org/tree-ops-ext#gid-6>
|
C3.2 | T | C2 | R3 |
"ADDISON
AV"
|
"ADDISON
AV"
|
<http://example.org/tree-ops-ext#gid-6>
|
C3.3 | T | C3 | R3 |
"Robinia
pseudoacacia"
|
"Robinia
pseudoacacia"
|
<http://example.org/tree-ops-ext#gid-6>
|
C3.4 | T | C4 | R3 |
"Large
Tree
Routine
Prune"
|
"Large
Tree
Routine
Prune"
(English)
|
<http://example.org/tree-ops-ext#gid-6>
|
C3.5 | T | C5 | R3 |
"29"
|
29
|
<http://example.org/tree-ops-ext#gid-6>
|
C3.6 | T | C6 | R3 |
"6/1/2010"
|
2010-06-01
|
<http://example.org/tree-ops-ext#gid-6>
|
C3.7 | T | C7 | R3 |
"cavity
or
decay;
trunk
decay;
codominant
leaders;
included
bark;
large
leader
or
limb
decay;
previous
failure
root
damage;
root
decay;
beware
of
BEES"
|
"cavity
or
decay"
,
"trunk
decay"
,
"codominant
leaders"
,
"included
bark"
,
"large
leader
or
limb
decay"
,
"previous
failure
root
damage"
,
"root
decay"
,
"beware
of
BEES"
|
<http://example.org/tree-ops-ext#gid-6>
|
C3.8 | T | C8 | R3 |
"YES"
|
true
|
<http://example.org/tree-ops-ext#gid-6>
|
C3.9 | T | C9 | R3 |
"<Point><coordinates>-122.156299,37.441151</coordinates></Point>"
|
"<Point><coordinates>-122.156299,37.441151</coordinates></Point>"
(XML)
|
<http://example.org/tree-ops-ext#gid-6>
|
Minimal mode output for this example is provided in Turtle [ turtle ] syntax below:
@base <http://example.org/tree-ops-ext.csv> . @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . @prefix xsd: <http://www.w3.org/2001/XMLSchema#> . <http://example.org/tree-ops-ext#gid-1> <#on_street> "ADDISON AV" ; <#species> "Celtis australis" ; <#trim_cycle> "Large Tree Routine Prune"@en ; <#dbh> 11 ; <#inventory_date> "2010-10-18"^^xsd:date ; <#protected> false ; <#kml> "<Point><coordinates>-122.156485,37.440963</coordinates></Point>"^^rdf:XMLLiteral . <http://example.org/tree-ops-ext#gid-2> <#on_street> "EMERSON ST" ; <#species> "Liquidambar styraciflua" ; <#trim_cycle> "Large Tree Routine Prune"@en ; <#dbh> 11 ; <#inventory_date> "2010-06-02"^^xsd:date ; <#protected> false ; <#kml> "<Point><coordinates>-122.156749,37.440958</coordinates></Point>"^^rdf:XMLLiteral . <http://example.org/tree-ops-ext#gid-6> <#on_street> "ADDISON AV" ; <#species> "Robinia pseudoacacia" ; <#trim_cycle> "Large Tree Routine Prune"@en ; <#dbh> 29 ; <#inventory_date> "2010-06-01"^^xsd:date ; <#comments> "cavity or decay", "trunk decay", "codominant leaders", "included bark", "large leader or limb decay", "previous failure root damage", "root decay", "beware of BEES" ; <#protected> true ; <# kml > "<Point><coordinates>-122.156299,37.441151</coordinates></Point>" ^^ rdf : XMLLiteral .
The
subject
described
by
each
row
is
explicitly
defined
using
the
about
URL
annotation;
e.g.
the
subject
of
row
R1
is
http://example.org/tree-ops-ext#gid-1
.
Output
for
column
C1
(
{
"name":
"GID"
}
)
is
not
included
as
the
column
suppress
output
annotation
is
true
.
A
language
tag
is
specified
for
values
of
column
C4
(
{
"name":
"trim_cycle"
}
)
as
the
cell
value
language
annotation
is
en
.
The
datatype
annotation
is
set
on
columns
C5
,
C6
,
C8
and
C9
(
{
"name":
"dbh"}
,
{
"name":
"inventory_date"
}
,
{
"name":
"protected"
}
and
{
"name":
"kml"
}
);
integer
,
date
,
boolean
and
xml
respectively.
The
datatype
property
is
inherited
by
all
cells
in
each
of
those
columns
,
therefore
the
RDF
output
for
those
cells
includes
the
appropriate
datatype
IRI
.
Cells
C1.7
and
C2.7
(
rows
R1
and
R2
;
column
,
{
"name":
"comments"
}
)
have
null
values
-
no
output
is
included
for
these
cells
.
Cell
C3.7
(
row
R3
;
column
,
{
"name":
"comments"
}
)
contains
an
unordered
sequence
of
values;
the
set
of
values
are
included
as
a
simple
set
of
triples
as
opposed
to
an
instance
of
rdf:List
as
the
ordered
annotation
has
defaulted
to
false
.
Standard mode output for this example is provided in Turtle [ turtle ] syntax below:
@base <http://example.org/tree-ops-ext.csv> . @prefix csvw: <http://www.w3.org/ns/csvw#> . @prefix dc: <http://purl.org/dc/terms/> . @prefix dcat: <http://www.w3.org/ns/dcat#> . @prefix oa: <http://www.w3.org/ns/oa#> . @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . @prefix schema: <http://schema.org/> . @prefix xsd: <http://www.w3.org/2001/XMLSchema#> . _:68fc08e5-56a0-47e2-a784-3a644d8257c4 a csvw:TableGroup ; csvw:table <http://example.org/tree-ops-ext> . <http://example.org/tree-ops-ext> a csvw:Table ; csvw:url <http://example.org/tree-ops-ext.csv> ; dc:title "Tree Operations"@en ; dcat:keyword "tree"@en, "street"@en, "maintenance"@en ; dc:publisher [ schema:name "Example Municipality"@en ; schema:url <http://example.org> ] ; dc:license <http://opendefinition.org/licenses/cc-by/> ; dc:modified "2010-12-31"^^xsd:date ; csvw:note [ a oa:Annotation ; oa:hasTarget <http://example.org/tree-ops-ext> ; oa:hasBody [ a oa:EmbeddedContent ; rdf:value "This is a very interesting comment about the table; it's a table!"@en ; dc:format "text/plain" ] ] ; csvw:row [ a csvw:Row ; csvw:rownum 1 ; csvw:url <#row=2> ; csvw:describes <http://example.org/tree-ops-ext#gid-1> ], [ a csvw:Row ; csvw:rownum 2 ; csvw:url <#row=3> ; csvw:describes <http://example.org/tree-ops-ext#gid-2> ], [ a csvw:Row ; csvw:rownum 3 ; csvw:url <#row=4> ; csvw:describes <http://example.org/tree-ops-ext#gid-6> ] . <http://example.org/tree-ops-ext#gid-1> <#on_street> "ADDISON AV" ; <#species> "Celtis australis" ; <#trim_cycle> "Large Tree Routine Prune"@en ; <#dbh> 11 ; <#inventory_date> "2010-10-18"^^xsd:date ; <#protected> false ; <#kml> "<Point><coordinates>-122.156485,37.440963</coordinates></Point>"^^rdf:XMLLiteral . <http://example.org/tree-ops-ext#gid-2> <#on_street> "EMERSON ST" ; <#species> "Liquidambar styraciflua" ; <#trim_cycle> "Large Tree Routine Prune"@en ; <#dbh> 11 ; <#inventory_date> "2010-06-02"^^xsd:date ; <#protected> false ; <#kml> "<Point><coordinates>-122.156749,37.440958</coordinates></Point>"^^rdf:XMLLiteral . <http://example.org/tree-ops-ext#gid-6> <#on_street> "ADDISON AV" ; <#species> "Robinia pseudoacacia" ; <#trim_cycle> "Large Tree Routine Prune"@en ; <#dbh> 29 ; <#inventory_date> "2010-06-01"^^xsd:date ; <#comments> "cavity or decay", "trunk decay", "codominant leaders", "included bark", "large leader or limb decay", "previous failure root damage", "root decay", "beware of BEES" ; <#protected> true ; <# kml > "<Point><coordinates>-122.156299,37.441151</coordinates></Point>" ^^ rdf : XMLLiteral .
Table
T
(
{
"url":
"http://example.org/tree-ops-ext.csv"}
)
has
been
explicitly
identified:
{
"@id":
"<http://exmple.org/tree-ops-ext>"}
.
Non-core
annotations
and
notes
specified
for
table
T
(
{
"url":
"http://example.org/tree-ops-ext.csv"}
)
are
included
in
the
output.
As
the
metadata
description
file
http://example.org/tree-ops-ext.csv-metadata.json
defines
a
default
language
within
the
context
(
"@context":
["http://www.w3.org/ns/csvw",
{"@language":
"en"}]
),
all
non-core
annotations
of
type
string
(e.g.
dc:title
,
dcat:keyword
,
dc:publisher
,
dc:license
and
dc:modified
)
are
expressed
in
the
RDF
output
using
the
the
appropriate
language
tag
.
This example uses a single annotated table describing a listing of music events. Each row from the tabular data file corresponds to three resources; the music event itself, the location where that event occurs and the offer to sell tickets for that event. The goal is to convert the CSV content into schema.org markup that a search engine such as Google can use to index music events. Details of how Google expects this information to be structured can be found here .
The
input
tabular
data
file,
published
at
http://example.org/events-listing.csv
,
and
the
associated
metadata
description
http://example.org/events-listing.csv-metadata.json
are
provided
below:
Name, Start Date, Location Name, Location Address, Ticket Url B.B. King,2014-04-12T19:30,"Lupo’s Heartbreak Hotel","79 Washington St., Providence, RI",https://www.etix.com/ticket/1771656 B.B. King,2014-04-13T20:00,"Lynn Auditorium","Lynn, MA, 01901",http://frontgatetickets.com/venue.php?id=11766
{ "@context": ["http://www.w3.org/ns/csvw", {"@language": "en"}], "url": "events-listing.csv", "dialect": {"trim": true}, "tableSchema": { "columns": [{ "name": "name", "titles": "Name", "aboutUrl": "#event-{_row}", "propertyUrl": "schema:name" }, { "name": "start_date", "titles": "Start Date", "datatype": { "base": "datetime", "format": "yyyy-MM-ddTHH:mm" }, "aboutUrl": "#event-{_row}", "propertyUrl": "schema:startDate" }, { "name": "location_name", "titles": "Location Name", "aboutUrl": "#place-{_row}", "propertyUrl": "schema:name" }, { "name": "location_address", "titles": "Location Address", "aboutUrl": "#place-{_row}", "propertyUrl": "schema:address" }, { "name": "ticket_url", "titles": "Ticket Url", "datatype": "anyURI", "aboutUrl": "#offer-{_row}", "propertyUrl": "schema:url" }, { "name": "type_event", "virtual": true, "aboutUrl": "#event-{_row}", "propertyUrl": "rdf:type", "valueUrl": "schema:MusicEvent" }, { "name": "type_place", "virtual": true, "aboutUrl": "#place-{_row}", "propertyUrl": "rdf:type", "valueUrl": "schema:Place" }, { "name": "type_offer", "virtual": true, "aboutUrl": "#offer-{_row}", "propertyUrl": "rdf:type", "valueUrl": "schema:Offer" }, { "name": "location", "virtual": true, "aboutUrl": "#event-{_row}", "propertyUrl": "schema:location", "valueUrl": "#place-{_row}" }, { "name": "offers", "virtual": true, "aboutUrl": "#event-{_row}", "propertyUrl": "schema:offers", "valueUrl": "#offer-{_row}" }] } }
The
CSV
to
RDF
translation
is
limited
to
providing
one
statement,
or
triple,
per
column
in
the
table
.
The
target
schema.org
markup
requires
10
statements
to
describe
each
event.
As
the
base
tabular
data
file
contains
5
columns,
an
additional
5
virtual
columns
have
been
added
in
order
to
provide
for
the
full
complement
of
statements—including
the
relationships
between
the
3
resources
(event,
location,
and
offer)
described
by
each
row
of
the
table
.
Note
that
the
virtual
annotation
is
set
to
true
for
these
virtual
columns
.
Furthermore, note that no attempt is made to reconcile between locations or offers that may be associated with more than one event; every row in the table will create both a new location resource and offer resource in addition to the event resource. If considered necessary, applications such as OpenRefine may be used to identify and reconcile duplicate location resources once the RDF output has been generated.
The annotated table generated from parsing the tabular data file and associated metadata is shown below and provides the basis for the conversion to RDF.
Annotations for the resulting table T , with 10 columns and 2 rows , are shown below:
id | core annotations | ||
---|---|---|---|
url | columns | rows | |
T |
http://example.org/events-listing.csv
|
C1 , C2 , C3 , C4 , C5 , C6 , C7 , C8 , C9 , C10 | R1 , R2 |
Annotations for the columns , rows and cells in table T are shown in the tables below.
Column annotations:
C1 | T | 1 | 1 | C1.1 , C2.1 |
name
|
Name
|
|
C2 | T | 2 | 2 | C1.2 , C2.2 |
start_date
|
Start
Date
|
|
C3 | T | 3 | 3 | C1.3 , C2.3 |
location_name
|
Location
Name
|
|
C4 | T | 4 | 4 | C1.4 , C2.4 |
location_address
|
Location
Address
|
|
C5 | T | 5 | 5 | C1.5 , C2.5 |
ticket_url
|
Ticket
Url
|
|
C6 | T | 6 | 6 | C1.6 , C2.6 |
type_event
|
true
|
|
C7 | T | 7 | 7 | C1.7 , C2.7 |
type_place
|
true
|
|
C8 | T | 8 | 8 | C1.8 , C2.8 |
type_offer
|
true
|
|
C9 | T | 9 | 9 | C1.9 , C2.9 |
location
|
true
|
|
C10 | T | 10 | 10 | C1.10 , C2.10 |
offers
|
true
|
Row annotations:
id | core annotations | |||
---|---|---|---|---|
table | number | source number | cells | |
R1 | T | 1 | 2 | C1.1 , C1.2 , C1.3 , C1.4 , C1.5 , C1.6 , C1.7 , C1.8 , C1.9 , C1.10 |
R2 | T | 2 | 3 | C2.1 , C2.2 , C2.3 , C2.4 , C2.5 , C2.6 , C2.7 , C2.8 , C2.9 , C2.10 |
Cell annotations:
id | core annotations | |||||||
---|---|---|---|---|---|---|---|---|
table | column | row | string value | value | about URL | property URL | value URL | |
C1.1 | T | C1 | R1 |
"B.B.
King"
|
"B.B.
King"
|
<http://example.org/events-listing.csv#event-1>
|
schema:name
|
|
C1.2 | T | C2 | R1 |
"2014-04-12T19:30"
|
2014-04-12T19:30:00
|
<http://example.org/events-listing.csv#event-1>
|
schema:startDate
|
|
C1.3 | T | C3 | R1 |
"Lupo’s
Heartbreak
Hotel"
|
"Lupo’s
Heartbreak
Hotel"
|
<http://example.org/events-listing.csv#place-1>
|
schema:name
|
|
C1.4 | T | C4 | R1 |
"79
Washington
St.,
Providence,
RI"
|
"79
Washington
St.,
Providence,
RI"
|
<http://example.org/events-listing.csv#place-1>
|
schema:address
|
|
C1.5 | T | C5 | R1 |
"https://www.etix.com/ticket/1771656"
|
<https://www.etix.com/ticket/1771656>
|
<http://example.org/events-listing.csv#offer-1>
|
schema:url
|
|
C1.6 | T | C6 | R1 |
""
|
null
|
<http://example.org/events-listing.csv#event-1>
|
rdf:type
|
schema:MusicEvent
|
C1.7 | T | C7 | R1 |
""
|
null
|
<http://example.org/events-listing.csv#place-1>
|
rdf:type
|
schema:Place
|
C1.8 | T | C8 | R1 |
""
|
null
|
<http://example.org/events-listing.csv#offer-1>
|
rdf:type
|
schema:Offer
|
C1.9 | T | C9 | R1 |
""
|
null
|
<http://example.org/events-listing.csv#event-1>
|
schema:location
|
<http://example.org/events-listing.csv#place-1>
|
C1.10 | T | C10 | R1 |
""
|
null
|
<http://example.org/events-listing.csv#event-1>
|
schema:offers
|
<http://example.org/events-listing.csv#offer-1>
|
C2.1 | T | C1 | R2 |
"B.B.
King"
|
"B.B.
King"
|
<http://example.org/events-listing.csv#event-2>
|
schema:name
|
|
C2.2 | T | C2 | R2 |
"2014-04-13T20:00"
|
2014-04-13T20:00:00
|
<http://example.org/events-listing.csv#event-2>
|
schema:startDate
|
|
C2.3 | T | C3 | R2 |
"Lynn
Auditorium"
|
"Lynn
Auditorium"
|
<http://example.org/events-listing.csv#place-2>
|
schema:name
|
|
C2.4 | T | C4 | R2 |
"Lynn,
MA,
01901"
|
"Lynn,
MA,
01901"
|
<http://example.org/events-listing.csv#place-2>
|
schema:address
|
|
C2.5 | T | C5 | R2 |
"http://frontgatetickets.com/venue.php?id=11766"
|
<http://frontgatetickets.com/venue.php?id=11766>
|
<http://example.org/events-listing.csv#offer-2>
|
schema:url
|
|
C2.6 | T | C6 | R2 |
""
|
null
|
<http://example.org/events-listing.csv#event-2>
|
rdf:type
|
schema:MusicEvent
|
C2.7 | T | C7 | R2 |
""
|
null
|
<http://example.org/events-listing.csv#place-2>
|
rdf:type
|
schema:Place
|
C2.8 | T | C8 | R2 |
""
|
null
|
<http://example.org/events-listing.csv#offer-2>
|
rdf:type
|
schema:Offer
|
C2.9 | T | C9 | R2 |
""
|
null
|
<http://example.org/events-listing.csv#event-2>
|
schema:location
|
<http://example.org/events-listing.csv#place-2>
|
C2.10 | T | C10 | R2 |
""
|
null
|
<http://example.org/events-listing.csv#event-2>
|
schema:offers
|
<http://example.org/events-listing.csv#offer-2>
|
Minimal mode output for this example is provided in Turtle [ turtle ] syntax below:
@base <http://example.org/events-listing.csv> . @prefix schema: <http://schema.org/> . @prefix xsd: <http://www.w3.org/2001/XMLSchema#> . <#event-1> a schema:MusicEvent ; schema:name "B.B. King" ; schema:startDate "2014-04-12T19:30:00"^^xsd:dateTime ; schema:location <#place-1> ; schema:offers <#offer-1> . <#place-1> a schema:Place ; schema:name "Lupo’s Heartbreak Hotel" ; schema:address "79 Washington St., Providence, RI" . <#offer-1> a schema:Offer ; schema:url "https://www.etix.com/ticket/1771656"^^xsd:anyURI . <#event-2> a schema:MusicEvent ; schema:name "B.B. King" ; schema:startDate "2014-04-13T20:00:00"^^xsd:dateTime ; schema:location <#place-2> ; schema:offers <#offer-2> . <#place-2> a schema:Place ; schema:name "Lynn Auditorium" ; schema:address "Lynn, MA, 01901" . <#offer-2> a schema:Offer ; schema : url "http://frontgatetickets.com/venue.php?id=11766" ^^ xsd : anyURI .
Three resources are defined for each row within the table; event, location, and offer.
Each
column
description
in
the
metadata
explicitly
defines
both
aboutUrl
and
propertyUrl
properties
which
are
used
to
create
the
about
URL
and
property
URL
annotations
on
the
column's
cells
.
Columns
C6
,
C7
and
C8
(
{
"name":
"type_event"}
,
{
"name":
"type_place"}
and
{
"name":
"type_offer"}
)
define
the
semantic
types
of
the
resources
described
by
each
row
:
schema:MusicEvent
,
schema:Place
and
schema:Offer
respectively.
Column
C9
(
{
"name":
"location"}
)
uses
the
about
URL
,
property
URL
and
value
URL
to
assert
the
relationship
between
the
event
and
location
resources.
Column
C10
(
{
"name":
"offer"}
)
uses
the
about
URL
,
property
URL
and
value
URL
to
assert
the
relationship
between
the
event
and
offer
resources.
Standard mode output for this example is provided in Turtle [ turtle ] syntax below:
@base <http://example.org/events-listing.csv> . @prefix csvw: <http://www.w3.org/ns/csvw#> . @prefix schema: <http://schema.org/> . @prefix xsd: <http://www.w3.org/2001/XMLSchema#> . _:95cc7970-ce99-44b0-900c-e2c2c028bbd3 a csvw:TableGroup ; csvw:table [ a csvw:Table ; csvw:url <http://example.org/events-listing.csv> ; csvw:row [ a csvw:Row ; csvw:rownum 1 ; csvw:url <#row=2> ; csvw:describes <#event-1>, <#place-1>, <#offer-1> ], [ a csvw:Row ; csvw:rownum 2 ; csvw:url <#row=3> ; csvw:describes <#event-2>, <#place-2>, <#offer-2> ] ] . <#event-1> a schema:MusicEvent ; schema:name "B.B. King" ; schema:startDate "2014-04-12T19:30:00"^^xsd:dateTime ; schema:location <#place-1> ; schema:offers <#offer-1> . <#place-1> a schema:Place ; schema:name "Lupo’s Heartbreak Hotel" ; schema:address "79 Washington St., Providence, RI" . <#offer-1> a schema:Offer ; schema:url "https://www.etix.com/ticket/1771656"^^xsd:anyURI . <#event-2> a schema:MusicEvent ; schema:name "B.B. King" ; schema:startDate "2014-04-13T20:00:00"^^xsd:dateTime ; schema:location <#place-2> ; schema:offers <#offer-2> . <#place-2> a schema:Place ; schema:name "Lynn Auditorium" ; schema:address "Lynn, MA, 01901" . <#offer-2> a schema:Offer ; schema : url "http://frontgatetickets.com/venue.php?id=11766" ^^ xsd : anyURI .
The
resources
described
by
each
row
are
explcitly
defined
using
the
about
URL
annotation
this
case
three
resources
per
row
(event,
location,
and
offer).
The
relationship
between
the
row
and
each
subject
resource
is
asserted
using
the
csvw:describes
property;
e.g.
for
row
R1
we
state
[]
csvw:describes
t1:event-1,
t1:place-1,
t1:offer-1
.
.
This example is based on Use Case #4 - Publication of public sector roles and salaries and uses four annotated tables published as a group of tables . Information about senior roles and junior roles within a government department or organization are published in CSV format by each department. These are validated against a centrally published schema to ensure that all the data published by departments is consistent. Additionally, lists of organizations and professions are also published centrally, providing controlled vocabularies against which departmental submissions are validated.
Information published about junior and senior roles provides summary information for each post within the government department or organization. Whilst the junior role information is anonymous, providing only an indication of the number of full-time-equivalent (FTE) staff occupying a given post, the senior role information specifies the named individual occupying each post. As such, each row from the tabular data file describing senior roles corresponds to two resources; the post and the person occupying that post.
This example is concerned only with converting the information provided each government department or organization not the centrally published information listing organizations and professions.
The input tabular data files and associated metadata descriptions are provided below:
Organization Unique Reference,Organization Name,Department Reference hefce.ac.uk,Higher Education Funding Council for England,bis.gov.uk bis.gov.uk,"Department for Business, Innovation and Skills",xx
Profession Finance Information Technology Operational Delivery Policy
Post Unique Reference,Name,Grade,Job Title,Reports to Senior Post,Profession,Organization Reference 90115,Steve Egan,SCS1A,Deputy Chief Executive,90334,Finance,hefce.ac.uk 90334,Sir Alan Langlands,SCS4,Chief Executive,xx,Policy,hefce.ac.uk
Reporting Senior Post,Grade,Payscale Minimum (£),Payscale Maximum (£),Generic Job Title,Number of Posts (FTE),Profession,Organization Reference 90115,4,17426,20002,Administrator,8.67,Operational Delivery,hefce.ac.uk 90115,5,19546,22478,Administrator,0.5,Operational Delivery,hefce.ac.uk
{ "@type": "TableGroup", "@context": ["http://www.w3.org/ns/csvw", {"@language": "en"}], "tables": [{ "url": "gov.uk/data/organizations.csv","tableSchema": "gov.uk/schema/organizations.json", "suppressOutput": true }, { "url": "gov.uk/data/professions.csv","tableSchema": "gov.uk/schema/professions.json", "suppressOutput": true }, { "url": "senior-roles.csv","tableSchema": "gov.uk/schema/senior-roles.json" }, { "url": "junior-roles.csv","tableSchema": "gov.uk/schema/junior-roles.json" }] }
{ "@id": "http://example.org/gov.uk/schema/organizations.json", "@context": "http://www.w3.org/ns/csvw", "columns": [{ "name": "ref", "titles": "Organization Unique Reference", "datatype": "string", "required": true, "propertyUrl": "dc:identifier" }, { "name": "name", "titles": "Organization Name", "datatype": "string", "propertyUrl": "foaf:name" }, { "name": "department", "titles": "Department Reference", "datatype": "string", "null": "xx", "propertyUrl": "org:subOrganizationOf","valueUrl": "http://example.org/organization/{department}" }], "primaryKey": "ref", "aboutUrl": "http://example.org/organization/{ref}", "foreignKeys": [{ "columnReference": "department", "reference": { "schemaReference": "http://example.org/gov.uk/schema/organizations.json", "columnReference": "ref" } }] }
{ "@id": "http://example.org/gov.uk/schema/professions.json", "@context": "http://www.w3.org/ns/csvw", "columns": [{ "name": "name", "titles": "Profession", "datatype": "string", "required": true }], "primaryKey": "name" }
{ "@id": "http://example.org/gov.uk/schema/senior-roles.json", "@context": "http://www.w3.org/ns/csvw", "columns": [{ "name": "ref", "titles": "Post Unique Reference", "datatype": "string", "required": true, "propertyUrl": "dc:identifier" }, { "name": "name", "titles": "Name", "datatype": "string", "aboutUrl": "http://example.org/organization/{organizationRef}/person/{_row}", "propertyUrl": "foaf:name" }, { "name": "grade", "titles": "Grade", "datatype": "string", "propertyUrl": "http://example.org/gov.uk/def/grade" }, { "name": "job", "titles": "Job Title", "datatype": "string", "propertyUrl": "http://example.org/gov.uk/def/job" }, { "name": "reportsTo", "titles": "Reports to Senior Post", "datatype": "string", "null": "xx", "propertyUrl": "org:reportsTo", "valueUrl": "http://example.org/organization/{organizationRef}/post/{reportsTo}" }, { "name": "profession", "titles": "Profession", "datatype": "string", "propertyUrl": "http://example.org/gov.uk/def/profession" }, { "name": "organizationRef", "titles": "Organization Reference", "datatype": "string", "propertyUrl": "org:postIn", "valueUrl": "http://example.org/organization/{organizationRef}", "required": true }, { "name": "post_holder", "virtual": true, "propertyUrl": "org:heldBy", "valueUrl": "http://example.org/organization/{organizationRef}/person/{_row}" }], "primaryKey": "ref", "aboutUrl": "http://example.org/organization/{organizationRef}/post/{ref}", "foreignKeys": [{ "columnReference": "reportsTo", "reference": { "schemaReference": "http://example.org/gov.uk/schema/senior-roles.json", "columnReference": "ref" } }, { "columnReference": "profession", "reference": { "schemaReference": "http://example.org/gov.uk/schema/professions.json", "columnReference": "name" } }, { "columnReference": "organizationRef", "reference": { "schemaReference": "http://example.org/gov.uk/schema/organizations.json", "columnReference": "ref" } }] }
{ "@id": "http://example.org/gov.uk/schema/junior-roles.json", "@context": "http://www.w3.org/ns/csvw", "columns": [{ "name": "reportsToSenior", "titles": "Reporting Senior Post", "datatype": "string", "propertyUrl": "org:reportsTo", "valueUrl": "http://example.org/organization/{organizationRef}/post/{reportsToSenior}", "required": true }, { "name": "grade", "titles": "Grade", "datatype": "string", "propertyUrl": "http://example.org/gov.uk/def/grade" }, { "name": "min_pay", "titles": "Payscale Minimum (£)", "datatype": "integer", "propertyUrl": "http://example.org/gov.uk/def/min_pay" }, { "name": "max_pay", "titles": "Payscale Maximum (£)", "datatype": "integer", "propertyUrl": "http://example.org/gov.uk/def/max_pay" }, { "name": "job", "titles": "Generic Job Title", "datatype": "string", "propertyUrl": "http://example.org/gov.uk/def/job" }, { "name": "number", "titles": "Number of Posts (FTE)", "datatype": "number", "propertyUrl": "http://example.org/gov.uk/def/number_of_posts" }, { "name": "profession", "titles": "Profession", "datatype": "string", "propertyUrl": "http://example.org/gov.uk/def/profession" }, { "name": "organizationRef", "titles": "Organization Reference", "datatype": "string", "propertyUrl": "org:postIn", "valueUrl": "http://example.org/organization/{organizationRef}", "required": true }], "foreignKeys": [{ "columnReference": "reportsToSenior", "reference": { "schemaReference": "http://example.org/gov.uk/schema/senior-roles.json", "columnReference": "ref" } }, { "columnReference": "profession", "reference": { "schemaReference": "http://example.org/gov.uk/schema/professions.json", "columns": "name" } }, { "columnReference": "organizationRef", "reference": { "schemaReference": "http://example.org/gov.uk/schema/organizations.json", "columns": "ref" } }] }
This
example
makes
extensive
use
of
the
example.org
domain.
As
described
in
[
RFC6761
],
this
domain
is
used
for
illustrative
examples
within
documentation.
In
reality,
the
resources
described
here
with
the
URL
path
/gov.uk
would
be
centrally
published
by
the
UK
Government
at,
say,
the
domain
data.gov.uk
.
Given
that
these
resources
are
centrally
published
with
an
aspiration
for
reuse,
the
schema
descriptions
have
been
factored
out
into
separate
resources.
As
such,
the
top-level
metadata
description
resource
metadata.json
simply
provides
the
list
of
tables
and
binds
each
of
them
to
the
appropriate
schema
that
is
defined
elsewhere.
Finally,
note
that
because
the
centrally
published
metadata
descriptions
are
intended
to
be
reused
across
many
government
departments
and
organizations,
extra
consideration
has
been
given
to
defining
URIs
for
the
person
and
post
resources
defined
in
each
row
of
the
senior
roles
tabular
data
and
subsequently
referenced
from
the
junior
roles
tabular
data.
To
ensure
that
naming
clashes
are
avoided,
the
unique
reference
for
the
organization
to
which
the
person
or
post
belongs
has
been
included
in
a
path
segment
of
the
identifier.
For
example,
the
URI
template
property
aboutUrl
used
to
identify
the
senior
post
is
specified
as
http://example.org/organization/{organizationRef}/post/{ref}
,
thus
yielding
the
URI
http://example.org/organization/hefce.ac.uk/post/90115
for
the
post
described
in
the
first
row
of
the
senior
roles
tabular
data.
The group of tables generated from parsing the tabular data files and associated metadata is shown below and provides the basis for the conversion to RDF.
Annotations for the group of tables G and the four tables Ta , Tb , Tc , and Td are shown below.
Group of Tables annotations:
id | core annotations |
---|---|
tables | |
G | Ta , Tb , Tc , Td |
Table annotations:
id | core annotations | ||||
---|---|---|---|---|---|
url
|
columns | rows | suppress output | foreign keys | |
Ta |
http://example.org/gov.uk/data/organizations.csv
|
Ca1 , Ca2 , Ca3 | Ra1 , Ra2 |
true
|
Fa1 |
Tb |
http://example.org/gov.uk/professions.csv
|
Cb1 | Rb1 , Rb2 , Rb3 , Rb4 |
true
|
|
Tc |
http://example.org/senior-roles.csv
|
Cc1 , Cc2 , Cc3 , Cc4 , Cc5 , Cc6 | Rc1 , Rc2 |
false
|
Fc1 , Fc2 , Fc3 |
Td |
http://example.org/junior-roles.csv
|
Cd1 , Cd2 , Cd3 , Cd4 , Cd5 , Cd6 , Cd7 | Rd1 , Rd2 |
false
|
Fd1 , Fd2 , Fd3 |
In
this
example,
output
for
the
centrally
published
lists
of
organizations
and
professions,
tables
Ta
and
Tb
(
http://example.org/gov.uk/data/organizations.csv
and
http://example.org/gov.uk/data/professions.csv
respectively),
are
not
required;
only
information
from
the
departmental
submissions
is
to
be
translated
to
RDF.
Note
the
suppress
output
annotation
on
this
table
.
The following foreign keys are defined:
id | columns in table | columns in referenced table |
---|---|---|
Fa1 | Ca3 | Ca1 |
Fc1 | Cc5 | Cc1 |
Fc2 | Cc6 | Cb1 |
Fc3 | Cc7 | Ca1 |
Fd1 | Cd1 | Cc1 |
Fd2 | Cd7 | Cb1 |
Fd3 | Cd8 | Ca1 |
Annotations for the columns , rows and cells in table T are shown in the tables below.
Column annotations:
id | core annotations | |||||||
---|---|---|---|---|---|---|---|---|
table | number | source number | cells | name | titles | required | virtual | |
Ca1 | Ta | 1 | 1 | Ca1.1 , Ca2.1 |
ref
|
Organization
Unique
Reference
|
true
|
|
Ca2 | Ta | 1 | 1 | Ca1.2 , Ca2.2 |
name
|
Organization
Name
|
||
Ca3 | Ta | 1 | 1 | Ca1.3 , Ca2.3 |
department
|
Department
Reference
|
||
Cb1 | Tb | 1 | 1 | Cb1.1 , Cb2.1 , Cb3.1 , Cb4.1 |
name
|
Profession
|
true
|
|
Cc1 | Tc | 1 | 1 | Cc1.1 , Cc2.1 |
ref
|
Post
Unique
Reference
|
true
|
|
Cc2 | Tc | 2 | 2 | Cc1.2 , Cc2.2 |
name
|
Name
|
||
Cc3 | Tc | 3 | 3 | Cc1.3 , Cc2.3 |
grade
|
Grade
|
||
Cc4 | Tc | 4 | 4 | Cc1.4 , Cc2.4 |
job
|
Job
Title
|
||
Cc5 | Tc | 5 | 5 | Cc1.5 , Cc2.5 |
reportsTo
|
Reports
to
Senior
Post
|
||
Cc6 | Tc | 6 | 6 | Cc1.6 , Cc2.6 |
profession
|
Profession
|
||
Cc7 | Tc | 7 | 7 | Cc1.7 , Cc2.7 |
organizationRef
|
Organization
Reference
|
true
|
|
Cc8 | Tc | 8 | 8 | Cc1.8 , Cc2.8 |
post_holder
|
true
|
||
Cd1 | Td | 1 | 1 | Cd1.1 , Cd2.1 |
reportsToSenior
|
Reporting
Senior
Post
|
true
|
|
Cd2 | Td | 2 | 2 | Cd1.2 , Cd2.2 |
grade
|
Grade
|
||
Cd3 | Td | 3 | 3 | Cd1.3 , Cd2.3 |
min_pay
|
Payscale
Minimum
(£)
|
||
Cd4 | Td | 4 | 4 | Cd1.4 , Cd2.4 |
max_pay
|
Payscale
Maximum
(£)
|
||
Cd5 | Td | 5 | 5 | Cd1.5 , Cd2.5 |
job
|
Generic
Job
Title
|
||
Cd6 | Td | 6 | 6 | Cd1.6 , Cd2.6 |
number
|
Number
of
Posts
(FTE)
|
||
Cd7 | Td | 7 | 7 | Cd1.7 , Cd2.7 |
profession
|
Profession
|
||
Cd8 | Td | 8 | 8 | Cd1.8 , Cd2.8 |
organizationRef
|
Organization
Reference
|
true
|
Column
Cc8
,
with
the
virtual
annotation
specified
as
true
,
is
used
to
relate
the
person
resource,
whose
name
is
provided
in
column
Cc2
,
to
the
associated
post
resource
within
the
current
row
of
table
Tc
(
{
"url":
"http://example.org/senior-roles.csv"
}
).
Row annotations:
id | core annotations | |||
---|---|---|---|---|
table | number | source number | cells | |
Ra1 | Ta | 1 | 2 | Ca1.1 , Ca1.2 , Ca1.3 |
Ra2 | Ta | 2 | 3 | Ca2.1 , Ca2.2 , Ca2.3 |
Rb1 | Tb | 1 | 2 | Cb1.1 |
Rb2 | Tb | 2 | 3 | Cb2.1 |
Rb3 | Tb | 3 | 4 | Cb3.1 |
Rb4 | Tb | 4 | 5 | Cb4.1 |
Rc1 | Tc | 1 | 2 | Cc1.1 , Cc1.2 , Cc1.3 , Cc1.4 , Cc1.5 , Cc1.6 , Cc1.7 , Cc1.8 |
Rc2 | Tc | 2 | 3 | Cc2.1 , Cc2.2 , Cc2.3 , Cc2.4 , Cc2.5 , Cc2.6 , Cc2.7 , Cc2.8 |
Rd1 | Td | 1 | 2 | Cd1.1 , Cd1.2 , Cd1.3 , Cd1.4 , Cd1.5 , Cd1.6 , Cd1.7 , Cd1.8 |
Rd2 | Td | 2 | 3 | Cd2.1 , Cd2.2 , Cd2.3 , Cd2.4 , Cd2.5 , Cd2.6 , Cd2.7 , Cd2.8 |
Cell annotations:
id | core annotations | |||||||
---|---|---|---|---|---|---|---|---|
table | column | row | string value | value | about URL | property URL | value URL | |
Ca1.1 | Ta | Ca1 | Ra1 |
"hefce.ac.uk"
|
"hefce.ac.uk"
|
<http://example.org/organization/hefce.ac.uk>
|
dc:identifier
|
|
Ca1.2 | Ta | Ca2 | Ra1 |
"Higher
Education
Funding
Council
for
England"
|
"Higher
Education
Funding
Council
for
England"
|
<http://example.org/organization/hefce.ac.uk>
|
foaf:name
|
|
Ca1.3 | Ta | Ca3 | Ra1 |
"bis.gov.uk"
|
"bis.gov.uk"
|
<http://example.org/organization/hefce.ac.uk>
|
org:subOrganizationOf
|
<http://example.org/organization/bis.gov.uk>
|
Ca2.1 | Ta | Ca1 | Ra2 |
"bis.gov.uk"
|
"bis.gov.uk"
|
<http://example.org/organization/bis.gov.uk>
|
dc:identifier
|
|
Ca2.2 | Ta | Ca2 | Ra2 |
"Department
for
Business,
Innovation
and
Skills"
|
"Department
for
Business,
Innovation
and
Skills"
|
<http://example.org/organization/bis.gov.uk>
|
foaf:name
|
|
Ca2.3 | Ta | Ca3 | Ra2 |
"xx"
|
null
|
<http://example.org/organization/bis.gov.uk>
|
org:subOrganizationOf
|
|
Cb1.1 | Tb | Cb1 | Rb1 |
"Finance"
|
"Finance"
|
|||
Cb2.1 | Tb | Cb1 | Rb2 |
"Information
Technology"
|
"Information
Techology"
|
|||
Cb3.1 | Tb | Cb1 | Rb3 |
"Operational
Delivery"
|
"Operational
Delivery"
|
|||
Cb4.1 | Tb | Cb1 | Rb4 |
"Policy"
|
"Policy"
|
|||
Cc1.1 | Tc | Cc1 | Rc1 |
"90115"
|
"90115"
|
<http://example.org/organization/hefce.ac.uk/post/90115>
|
dc:identifier
|
|
Cc1.2 | Tc | Cc2 | Rc1 |
"Steve
Egan"
|
"Steve
Egan"
|
<http://example.org/organization/hefce.ac.uk/person/1>
|
foaf:name
|
|
Cc1.3 | Tc | Cc3 | Rc1 |
"SCS1A"
|
"SCS1A"
|
<http://example.org/organization/hefce.ac.uk/post/90115>
|
<http://example.org/gov.uk/def/grade>
|
|
Cc1.4 | Tc | Cc4 | Rc1 |
"Deputy
Chief
Executive"
|
"Deputy
Chief
Executive"
|
<http://example.org/organization/hefce.ac.uk/post/90115>
|
<http://example.org/gov.uk/def/job>
|
|
Cc1.5 | Tc | Cc5 | Rc1 |
"90334"
|
"90334"
|
<http://example.org/organization/hefce.ac.uk/post/90115>
|
org:reportsTo
|
<http://example.org/organization/hefce.ac.uk/post/90334>
|
Cc1.6 | Tc | Cc6 | Rc1 |
"Finance"
|
"Finance"
|
<http://example.org/organization/hefce.ac.uk/post/90115>
|
<http://example.org/gov.uk/def/profession>
|
|
Cc1.7 | Tc | Cc7 | Rc1 |
"hefce.ac.uk"
|
"hefce.ac.uk"
|
<http://example.org/organization/hefce.ac.uk/post/90115>
|
org:postIn
|
<http://example.org/organization/hefce.ac.uk>
|
Cc1.8 | Tc | Cc8 | Rc1 |
""
|
null
|
<http://example.org/organization/hefce.ac.uk/post/90115>
|
org:heldBy
|
<http://example.org/organization/hefce.ac.uk/person/1>
|
Cc2.1 | Tc | Cc1 | Rc2 |
"90334"
|
"90334"
|
<http://example.org/organization/hefce.ac.uk/post/90334>
|
dc:identifier
|
|
Cc2.2 | Tc | Cc2 | Rc2 |
"Sir
Alan
Langlands"
|
"Sir
Alan
Langlands"
|
<http://example.org/organization/hefce.ac.uk/person/2>
|
foaf:name
|
|
Cc2.3 | Tc | Cc3 | Rc2 |
"SCS4"
|
"SCS4"
|
<http://example.org/organization/hefce.ac.uk/post/90334>
|
<http://example.org/gov.uk/def/grade>
|
|
Cc2.4 | Tc | Cc4 | Rc2 |
"Chief
Executive"
|
"Chief
Executive"
|
<http://example.org/organization/hefce.ac.uk/post/90334>
|
<http://example.org/gov.uk/def/job>
|
|
Cc2.5 | Tc | Cc5 | Rc2 |
"xx"
|
null
|
<http://example.org/organization/hefce.ac.uk/post/90334>
|
org:reportsTo
|
|
Cc2.6 | Tc | Cc6 | Rc2 |
"Policy"
|
"Policy"
|
<http://example.org/organization/hefce.ac.uk/post/90334>
|
<http://example.org/gov.uk/def/profession>
|
|
Cc2.7 | Tc | Cc7 | Rc2 |
"hefce.ac.uk"
|
"hefce.ac.uk"
|
<http://example.org/organization/hefce.ac.uk/post/90334>
|
org:postIn
|
<http://example.org/organization/hefce.ac.uk>
|
Cc2.8 | Tc | Cc8 | Rc2 |
""
|
null
|
<http://example.org/organization/hefce.ac.uk/post/90334>
|
org:heldBy
|
<http://example.org/organization/hefce.ac.uk/person/2>
|
Cd1.1 | Td | Cd1 | Rd1 |
"90115"
|
"90115"
|
org:reportsTo
|
<http://example.org/organization/hefce.ac.uk/post/90115>
|
|
Cd1.2 | Td | Cd2 | Rd1 |
"4"
|
"4"
|
<http://example.org/gov.uk/def/grade>
|
||
Cd1.3 | Td | Cd3 | Rd1 |
"17426"
|
17426
|
<http://example.org/gov.uk/def/min_pay>
|
||
Cd1.4 | Td | Cd4 | Rd1 |
"20002"
|
20002
|
<http://example.org/gov.uk/def/max_pay>
|
||
Cd1.5 | Td | Cd5 | Rd1 |
"Administrator"
|
"Administrator"
|
<http://example.org/gov.uk/def/job>
|
||
Cd1.6 | Td | Cd6 | Rd1 |
"8.67"
|
8.67
|
<http://example.org/gov.uk/def/number_of_posts>
|
||
Cd1.7 | Td | Cd7 | Rd1 |
"Operational
Delivery"
|
"Operational
Delivery"
|
<http://example.org/gov.uk/def/profession>
|
||
Cd1.8 | Td | Cd8 | Rd1 |
"hefce.ac.uk"
|
"hefce.ac.uk"
|
org:postIn
|
<http://example.org/organization/hefce.ac.uk>
|
|
Cd2.1 | Td | Cd1 | Rd2 |
"90115"
|
"90115"
|
org:reportsTo
|
<http://example.org/organization/hefce.ac.uk/post/90115>
|
|
Cd2.2 | Td | Cd2 | Rd2 |
"5"
|
"5"
|
<http://example.org/gov.uk/def/grade>
|
||
Cd2.3 | Td | Cd3 | Rd2 |
"19546"
|
19546
|
<http://example.org/gov.uk/def/min_pay>
|
||
Cd2.4 | Td | Cd4 | Rd2 |
"22478"
|
22478
|
<http://example.org/gov.uk/def/max_pay>
|
||
Cd2.5 | Td | Cd5 | Rd2 |
"Administrator"
|
"Administrator"
|
<http://example.org/gov.uk/def/job>
|
||
Cd2.6 | Td | Cd6 | Rd2 |
"0.5"
|
0.5
|
<http://example.org/gov.uk/def/number_of_posts>
|
||
Cd2.7 | Td | Cd7 | Rd2 |
"Operational
Delivery"
|
"Operational
Delivery"
|
<http://example.org/gov.uk/def/profession>
|
||
Cd2.8 | Td | Cd8 | Rd2 |
"hefce.ac.uk"
|
"hefce.ac.uk"
|
org:postIn
|
<http://example.org/organization/hefce.ac.uk>
|
Notice
that
value
URL
is
not
specified
for
cells
Ca2.3
and
Cc2.5
because
in
each
case
the
cell
value
is
null
and
the
virtual
annotation
of
column
Cb5
is
not
defined.
Minimal mode output for this example is provided in Turtle [ turtle ] syntax below:
@prefix dc: <http://purl.org/dc/terms/> . @prefix foaf: <http://xmlns.com/foaf/0.1/> . @prefix org: <http://www.w3.org/ns/org#> . @prefix xsd: <http://www.w3.org/2001/XMLSchema#> . <http://example.org/organization/hefce.ac.uk/post/90115> dc:identifier "90115" ; org:heldBy <http://example.org/organization/hefce.ac.uk/person/1> ; <http://example.org/gov.uk/def/grade> "SCS1A" ; <http://example.org/gov.uk/def/job> "Deputy Chief Executive" ; org:reportsTo <http://example.org/organization/hefce.ac.uk/post/90334> ; <http://example.org/gov.uk/def/profession> "Finance" ; org:postIn <http://example.org/organization/hefce.ac.uk> . <http://example.org/organization/hefce.ac.uk/person/1> foaf:name "Steve Egan" . <http://example.org/organization/hefce.ac.uk/post/90334> dc:identifier "90334" ; org:heldBy <http://example.org/organization/hefce.ac.uk/person/2> ; <http://example.org/gov.uk/def/grade> "SCS4" ; <http://example.org/gov.uk/def/job> "Chief Executive" ; <http://example.org/gov.uk/def/profession> "Policy" ; org:postIn <http://example.org/organization/hefce.ac.uk> . <http://example.org/organization/hefce.ac.uk/person/2> foaf:name "Sir Alan Langlands" . _:d8b8e40c-8c74-458b-99f7-64d1cf5c65f2 org:reportsTo <http://example.org/organization/hefce.ac.uk/post/90115> ; <http://example.org/gov.uk/def/grade> "4" ; <http://example.org/gov.uk/def/min_pay> "17426"^^xsd:integer ; <http://example.org/gov.uk/def/max_pay> "20002"^^xsd:integer ; <http://example.org/gov.uk/def/job> "Administrator" ; <http://example.org/gov.uk/def/number_of_posts> "8.67"^^xsd:double ; <http://example.org/gov.uk/def/profession> "Operational Delivery" ; org:postIn <http://example.org/organization/hefce.ac.uk> . _:fa1fa954-dd5f-4aa1-b2bc-20bf9867fac6 org:reportsTo <http://example.org/organization/hefce.ac.uk/post/90115> ; <http://example.org/gov.uk/def/grade> "5" ; <http://example.org/gov.uk/def/min_pay> "19546"^^xsd:integer ; <http://example.org/gov.uk/def/max_pay> "22478"^^xsd:integer ; <http://example.org/gov.uk/def/job> "Administrator" ; <http://example.org/gov.uk/def/number_of_posts> "0.5"^^xsd:double ; <http://example.org/gov.uk/def/profession> "Operational Delivery" ; org : postIn < http : //example.org/organization/hefce.ac.uk> .
Output
for
tables
Ta
and
Tb
(
{
"url":
"http://example.org/gov.uk/data/organizations.csv"
}
and
{
"url":
"http://example.org/gov.uk/data/professions.csv"
}
)
are
not
included
as
the
suppress
output
annotation
is
true
.
The property URL is specified for all cells in tables Tc and Td .
Columns
Cc5
and
Cd1
(
{
"name":
"reportsTo"
}
and
{
"name":
"reportsToSenior"
}
)
use
the
about
URL
,
property
URL
and
value
URL
annotations
to
assert
the
relationship
between
the
given
post
and
the
senior
post
it
reports
to
for
the
cells
therein.
Similarly,
columns
Cc7
and
Cd8
(both
with
{
"name":
"organizationRef"
}
)
use
the
about
URL
,
property
URL
and
value
URL
annotations
to
assert
the
relationship
between
the
given
post
and
the
organization
to
which
it
belongs
for
the
cells
those
columns
.
Finally,
note
that
two
resources
are
created
for
each
row
within
table
Tc
(
{
"url":
"http://example.org/senior-roles.csv"
}
):
the
person
and
the
post
they
occupy.
The
relationship
between
these
resources
is
specified
via
virtual
column
Cc8
(
{
"name":
"post_holder"
}
)
using
the
about
URL
,
property
URL
and
value
URL
annotations.
Standard mode output for this example is provided in Turtle [ turtle ] syntax below:
@prefix csvw: <http://www.w3.org/ns/csvw#> . @prefix dc: <http://purl.org/dc/terms/> . @prefix foaf: <http://xmlns.com/foaf/0.1/> . @prefix org: <http://www.w3.org/ns/org#> . @prefix xsd: <http://www.w3.org/2001/XMLSchema#> . _:3d36cfbb-d2d5-4573-a1a7-3bf817062db8 a csvw:TableGroup ; csvw:table [ a csvw:Table ; csvw:url <http://example.org/senior-roles.csv> ; csvw:row [ a csvw:Row ; csvw:rownum "1"^^xsd:integer ; csvw:url <http://example.org/senior-roles.csv#row=2> ; csvw:describes <http://example.org/organization/hefce.ac.uk/post/90115>, <http://example.org/organization/hefce.ac.uk/person/1> ], [ a csvw:Row ; csvw:rownum "2"^^xsd:integer ; csvw:url <http://example.org/senior-roles.csv#row=3> ; csvw:describes <http://example.org/organization/hefce.ac.uk/post/90334>, <http://example.org/organization/hefce.ac.uk/person/2> ] ], [ a csvw:Table ; csvw:url <http://example.org/junior-roles.csv> ; csvw:row [ a csvw:Row ; csvw:rownum "1"^^xsd:integer ; csvw:url <http://example.org/junior-roles.csv#row=2> ; csvw:describes _:d8b8e40c-8c74-458b-99f7-64d1cf5c65f2 ], [ a csvw:Row ; csvw:rownum "2"^^xsd:integer ; csvw:url <http://example.org/junior-roles.csv#row=3> ; csvw:describes _:fa1fa954-dd5f-4aa1-b2bc-20bf9867fac6 ] ] . <http://example.org/organization/hefce.ac.uk/post/90115> dc:identifier "90115" ; org:heldBy <http://example.org/organization/hefce.ac.uk/person/1> ; <http://example.org/gov.uk/def/grade> "SCS1A" ; <http://example.org/gov.uk/def/job> "Deputy Chief Executive" ; org:reportsTo <http://example.org/organization/hefce.ac.uk/post/90334> ; <http://example.org/gov.uk/def/profession> "Finance" ; org:postIn <http://example.org/organization/hefce.ac.uk> . <http://example.org/organization/hefce.ac.uk/person/1> foaf:name "Steve Egan" . <http://example.org/organization/hefce.ac.uk/post/90334> dc:identifier "90334" ; org:heldBy <http://example.org/organization/hefce.ac.uk/person/2> ; <http://example.org/gov.uk/def/grade> "SCS4" ; <http://example.org/gov.uk/def/job> "Chief Executive" ; <http://example.org/gov.uk/def/profession> "Policy" ; org:postIn <http://example.org/organization/hefce.ac.uk> . <http://example.org/organization/hefce.ac.uk/person/2> foaf:name "Sir Alan Langlands" . _:d8b8e40c-8c74-458b-99f7-64d1cf5c65f2 org:reportsTo <http://example.org/organization/hefce.ac.uk/post/90115> ; <http://example.org/gov.uk/def/grade> "4" ; <http://example.org/gov.uk/def/min_pay> "17426"^^xsd:integer ; <http://example.org/gov.uk/def/max_pay> "20002"^^xsd:integer ; <http://example.org/gov.uk/def/job> "Administrator" ; <http://example.org/gov.uk/def/number_of_posts> "8.67"^^xsd:double ; <http://example.org/gov.uk/def/profession> "Operational Delivery" ; org:postIn <http://example.org/organization/hefce.ac.uk> . _:fa1fa954-dd5f-4aa1-b2bc-20bf9867fac6 org:reportsTo <http://example.org/organization/hefce.ac.uk/post/90115> ; <http://example.org/gov.uk/def/grade> "5" ; <http://example.org/gov.uk/def/min_pay> "19546"^^xsd:integer ; <http://example.org/gov.uk/def/max_pay> "22478"^^xsd:integer ; <http://example.org/gov.uk/def/job> "Administrator" ; <http://example.org/gov.uk/def/number_of_posts> "0.5"^^xsd:double ; <http://example.org/gov.uk/def/profession> "Operational Delivery" ; org : postIn < http : //example.org/organization/hefce.ac.uk> .
Table group G was explicitly defined, but has not been explicitly identified; the table group and table resources are treated as blank nodes .
The
person
and
post
resources
described
by
each
row
of
table
Tc
(
{
"url":
"http://example.org/senior-roles.csv"}
)
are
explcitly
defined
using
the
aboutUrl
property;
therefore,
say,
for
row
Rc1
we
state
[]
csvw:describes
<http://example.org/organization/hefce.ac.uk/post/90115>,
<http://example.org/organization/hefce.ac.uk/person/1>
.
;
whilst
the
aboutUrl
property
has
not
been
defined
for
resources
described
by
each
row
of
table
Td
(
{
"url":
"http://example.org/junior-roles.csv"}
);
therefore
blank
nodes
are
used,
e.g.
for
row
Rd1
we
state
[]
csvw:describes
_:d8b8e40c-8c74-458b-99f7-64d1cf5c65f2
.
.
This section is non-normative.
The "Direct Mapping of Relational Data to RDF" W3C Recommendation [ rdb-direct-mapping ] defines a simple transformation (referred to as direct mapping ) from a relational representation of data to RDF. The direct mapping takes as input a relational database (data and schema), and generates an RDF graph called the direct graph . Tables in a relational databases bear a strong resemblence to tabular data as defined in [ tabular-data-model ]; this section highlights the similarities and differences between the direct mapping and the tabular data mapping defined by this document. The following statements summarize the relationships:
The rest of this section will provide some examples. These are somewhat simplified forms of the examples as used in the [ rdb-direct-mapping ] document.
Consider
a
simple
table
in
a
relational
database,
called
People
:
PK | ||
ID | fname | addr |
---|---|---|
7 | Bob | 18 |
A relational table always has a schema that the direct mapping makes use of. In this example, the schema defines that:
ID
,
fname
,
and
addr
.
ID
are
the
primary
keys
in
the
table,
and
the
corresponding
cells
contain
integers.
fname
column
contain
strings.
addr
column
contain
integers.
Using the schema information, the direct graph is as follows (see [ rdb-direct-mapping ] for further details):
<http://foo.example.org/DB/People/ID=7> rdf:type <http://foo.example.org/DB/People>; <http://foo.example.org/DB/People/#ID> 7; <http://foo.example.org/DB/People/#fname> "Bob"; <http://foo.example.org/DB/People/#addr> 18.
where
http://foo.example.org/DB/
is
the
URL
for
the
database
containing
the
People
table.
When exporting the table into CSV the column names would naturally be mapped on the titles of the respective columns. The ( minimal ) tabular data mapping yields:
[ <http://foo.example.org/CSV/People/#ID> "7"; <http://foo.example.org/CSV/People/#fname> "Bob"; <http://foo.example.org/CSV/People/#addr> "18"; ]
where
http://foo.example.org/CSV/People
is
the
URL
of
the
CSV
file
exported
from
the
relational
database.
Comparing the two conversion results:
rdf:type
to
the
direct
graph
.
However,
by
default
(e.g.,
without
additional
annotation),
the
tabular
data
mapping
has
insufficient
information
to
make
such
an
assertion.
It is, however, possible to add annotation to the tabular data so that the two graphs would be semantically equivalent. Indeed, consider the following metadata using the definitions of the [ tabular-metadata ] specification:
{ "@context": "http://www.w3.org/ns/csvw", "tableSchema": { "url" : "http://foo.example.org/CSV/People", "aboutUrl" : "http://foo.example.org/CSV/People/ID={ID}", "columns": [{ "name": "ID", "datatype" : "integer" }, { "name": "fname", }, { "name": "addr", "datatype" : "integer" }, { "name": "type", "virtual": true, "propertyUrl": "rdf:type", "valueUrl" : "http://foo.example.org/CSV/People" }], } }
The
metadata
adds
annotations
on
datatypes,
adds
the
RDF
typing
triple
explicitly
(using
a
virtual
column
),
and
uses
the
aboutUrl
URL
template
property
to
provide
the
common
subject.
Essentially,
the
metadata
provides
the
information
that
the
direct
mapping
retrieves
from
the
table
schema.
The [ tabular-metadata ] specification includes an annotation for primary keys . However, that annotation is used for validation and does not influence the tabular data mapping , hence it is not included in the example metadata.
A processor exporting the table into a CSV file could also generate such a metadata automatically.
Consider
a
two
interrelated
simple
tables
in
a
relational
database,
called
People
and
Addresses
,
respectively:
PK | → Addresses(ID) | |
ID | fname | addr |
---|---|---|
7 | Bob | 18 |
PK | ||
ID | city | state |
---|---|---|
18 | Cambridge | MA |
Beyond
what
is
already
specified
for
the
People
table
the
corresponding
relational
schema
also
specifies
that:
Addresses
table
has
three
columns
named
ID
,
city
,
and
state
.
ID
are
primary
keys
in
the
Addresses
table,
and
the
corresponding
cells
contain
integers.
city
and
state
columns
in
the
Addresses
table
contain
strings
addr
column
of
the
People
table
are
foreign
keys
that
reference
the
ID
field
of
the
Addresses
table.
Using the schema information, the direct graph is as follows (see [ rdb-direct-mapping ] for further details):
<http://foo.example.org/DB/People/ID=7> rdf:type <http://foo.example.org/DB/People>;
<http://foo.example.org/DB/People#ID> 7;
<http://foo.example.org/DB/People#fname> "Bob";
<http://foo.example.org/DB/People#addr> 18;
<http://foo.example.org/DB/People#ref-addr> <http://foo.example.org/DB/Addresses/ID=18>.
<http://foo.example.org/DB/Addresses/ID=18> rdf:type <http://foo.example.org/DB/Addresses>;
<http://foo.example.org/DB/Addresses#ID> 18;
<http://foo.example.org/DB/Addresses#city> "Cambridge";
<http://foo.example.org/DB/Addresses#state>
"MA".
Note
the
highlighted
RDF
triple
linking
to
the
relevant
row
of
the
Addresses
table;
this
corresponds
to
the
foreign
key
in
the
schema.
Using the following metadata the tabular data mapping yields a semantically equivalent result:
{ "@context": "http://www.w3.org/ns/csvw", "resources" : [{ "url": "http://foo.example.org/CSV/People", "aboutUrl" : "http://foo.example.org/CSV/People/ID={ID}", "tableSchema": { "columns": [{ "name": "ID", "datatype": "integer" }, { "name": "fname", }, { "name": "addr", "datatype": "integer" }, { "name": "ref", "virtual": true, "propertyUrl": "http://foo.example.org/CSV/People#ref-addr", "valueUrl" : "http://foo.example.org/CSV/Addresses/ID={addr}" }, { "name": "type", "virtual": true, "propertyUrl": "rdf:type", "valueUrl" : "http://foo.example.org/CSV/People" }], } }, { "url": "http://foo.example.org/CSV/Addresses", "aboutUrl" : "http://foo.example.org/CSV/Addresses/ID={ID}", "tableSchema": [{ "columns": [{ "name": "ID", "datatype": "integer" }, { "name": "city", }, { "name": "state", }, { "name": "type", "virtual": true, "propertyUrl": "rdf:type", "valueUrl" : "http://foo.example.org/CSV/Addresses" }], }] }
Consider
a
case
with
three,
interrelated
simple
tables
in
a
relational
database,
called
People
,
Addresses
,
and
Departments
,
respectively:
PK | → Addresses(ID) | → Department(name,city) | ||
ID | fname | addr | deptName | deptCity |
---|---|---|---|---|
7 | Bob | 18 | accounting | Cambridge |
PK | ||
ID | city | state |
---|---|---|
18 | Cambridge | MA |
PK | Unique Key | |
ID | name | city |
---|---|---|
23 | accounting | Cambridge |
The corresponding relational schema specifies that
People
table
ID
,
name
,
addr
,
deptName
,
and
deptCity
.
ID
are
the
primary
keys
in
the
table,
and
the
corresponding
cells
contain
integers.
name
,
deptName
,
and
deptCity
columns
contain
strings.
addr
columns
contains
integers.
Addresses
table
ID
,
city
,
and
state
.
ID
are
the
primary
keys
in
the
table,
and
the
corresponding
cells
contain
integers.
city
and
state
columns
contain
strings.
Departments
table
ID
,
name
,
and
city
.
ID
are
the
primary
keys
in
the
table,
and
the
corresponding
cells
contain
integers.
name
and
city
columns
contain
strings.
name
and
city
are
unique
keys.
addr
column
of
the
People
table
are
foreign
keys
that
reference
the
ID
field
of
the
Addresses
table.
deptName
and
deptCity
columns
in
the
People
table
are
combined
foreign
keys
referencing
candidate
keys
for
the
name
and
city
pairs
of
the
Departments
table.
Using the schema information, the direct graph is as follows (see [ rdb-direct-mapping ] for further details):
<http://foo.example.org/DB/People/ID=7> rdf:type <http://foo.example.org/DB/People>;
<http://foo.example.org/DB/People/#ID> 7;
<http://foo.example.org/DB/People/#fname> "Bob";
<http://foo.example.org/DB/People/#addr> 18;
<http://foo.example.org/DB/People/#ref-addr> <http://foo.example.org/DB/Addresses/ID=18>;
<http://foo.example.org/DB/People/#deptName> "accounting";
<http://foo.example.org/DB/People/#deptCity> "Cambridge";
<http://foo.example.org/DB/People/#ref-deptName;deptCity> <http://foo.example.org/DB/Department/ID=23>.
<http://foo.example.org/DB/Addresses/ID=18> rdf:type <http://foo.example.org/DB/Addresses>;
<http://foo.example.org/DB/Addresses/#ID> 18;
<http://foo.example.org/DB/Addresses/#city> "Cambridge";
<http://foo.example.org/DB/Addresses/#addr> "MA".
<http://foo.example.org/DB/Departments/ID=23> rdf:type <http://foo.example.org/DB/Addresses>;
<http://foo.example.org/DB/Departments/#ID> 23;
<http://foo.example.org/DB/Departments/#name> "accounting";
<http://foo.example.org/DB/Departments/#city>
"Cambridge".
The
major
difference,
compared
to
the
simpler
example
with
foreign
keys
is
the
usage
of
unique
keys.
To
generate
the
right
object
URI
in
the
highlighted
statement
of
the
direct
graph
the
processor
has
to
find
that
unique
key
combination
in
the
Departments
table
and,
using
that
combination,
has
to
establish
the
subject
for
that
specific
row
that
can
is
to
be
used
as
an
object
URI
in
the
highlighted
statement.
This
can
be
done
because
the
direct
mapping
processor
has
simultaneous
access
to
several
tables
within
the
same
relational
database.
It
is
therefore
straightforward
to
access
all
the
tables
in
parallel
and
establish
the
necessary
relationships
to
generate
the
triples.
However, this combination cannot be handled by the tabular data mapping . The situation for tabular data is indeed different: tables are typically generated from single and, potentially, very large CSV files, meaning that a tabular data mapping processor cannot be expected to handle several tables in parallel. That is the reason why the [ tabular-data-model ] does not include features that would require such parallel access. However, as a consequence, the output of the direct mapping for such tables cannot be reproduced by the tabular data mapping .
Note that the [ tabular-data-model ] includes an annotation for transformations ; implementations may include scripts or templates to transform the output of the tabular data mapping and generate the required RDF graph.
@id
annotation
in
the
model.
The document has undergone substantial changes since the first public working draft . Below are some of the changes made: