Abstract

This document defines the procedures and rules to be applied when converting tabular data into JSON. 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 JSON.

Status of This Document

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

Table of Contents

1. Introduction

This document describes the processing of tabular data to create a set of nested objects that MUST be serialized as JSON [ RFC7159 ].

Note

The conversion of CSV content to JSON is intended for web developers who need not care about the complexities of RDF [ rdf11-concepts ]. Where the formality of RDF is required, [ csv2rdf ] provides the procedures for mapping from CSV content to RDF which may be serialized to [ json-ld ].

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 within the output.

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 JSON output described in this specification as input.

2. Conformance

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 and MUST 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).

Note

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

3. Typographical conventions

The following typographic conventions are used in this specification:

markup
Markup (elements, attributes, properties), machine processable values (string, characters, media types), property name, or a file name is in red-orange monospace font.
variable
A variable in pseudo-code or in an algorithm description is in italics.
definition
A definition of a term, to be used elsewhere in this or other specifications, is in bold and italics.
definition reference
A reference to a definition in this document is underlined and is also an active link to the definition itself.
markup definition reference
A references to a definition in this document , when the reference itself is also a markup, is underlined, red-orange monospace font, and is also an active link to the definition itself.
external definition reference
A reference to a definition in another document is underlined, in italics, and is also an active link to the definition itself.
markup external definition reference
A reference to a definition in another document , when the reference itself is also a markup, is underlined, in italics red-orange monospace font, and is also an active link to the definition itself.
hyperlink
A hyperlink is underlined and in blue.
[reference]
A document reference (normative or informative) is enclosed in square brackets and links to the references section.
Note

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.

Example 1
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.

4. Converting Tabular Data to JSON

The procedures for converting tabular data into JSON are described below for both standard and minimal modes.

4.1 Algorithm terms

about URL
The about URL annotation on the current cell . As defined in [ tabular-data-model ].
annotated table
The annotated table is defined in [ tabular-data-model ] as describing a particular table and its annotations.
array
An array is defined in JSON ([ RFC7159 ]) as an ordered sequence of zero or more values, where a value is a string, number, boolean, null, object , or array .
cell
A cell is defined in [ tabular-data-model ] as the intersection of a row and a column within a table .
cell errors
Cell errors are defined in [ tabular-data-model ] as a (possibly empty) list of validation errors generated while parsing the literal content of a cell to generate the semantic value .
cell value
A cell value is defined in [ tabular-data-model ] as the semantic value of the cell ; this MAY be null or a sequence of values.
column
A column is defined in [ tabular-data-model ] as a vertical arrangement of cells within a table .
group of tables
A group of tables is defined in [ tabular-data-model ] as comprising a set of annotated tables and a set of annotations that relate to that group.
group of tables identifier
The group of tables identifier is the id annotation on a group of tables . As defined in [ tabular-data-model ].
name
In the context of this specification, name is used as defined in JSON ([ RFC7159 ]); that is, that name is a string that provides a unique key within a set of name-value pairs within a JSON object .
non-core annotations
Core annotations are listed in [ tabular-data-model ]; groups of tables and tables may also have other annotations that are not defined in that specification; these are known as non-core annotations .
notes
A list of notes , as defined in [ tabular-data-model ], attached to an annotated table or group of tables using the notes property. This may be an empty list.
object
An object is defined in JSON ([ RFC7159 ]) as unordered collection of zero or more name-value pairs, where a name is a string and a value is a string, number, boolean, null, object , or array .
property URL
The property URL annotation on the current cell . As defined in [ tabular-data-model ].
row
The row is defined in [ tabular-data-model ] as a horizontal arrangement of cells within a table .
row number
A row number is defined in [ tabular-data-model ] as the position of the row within the table , starting from 1.
row source number
A row source number is defined in [ tabular-data-model ] as the position of the row within the source tabular data file . Provision of the row source number is dependent on parsing applications and may be reported as null .
subject
Within this algorithm, a subject is the resource that the value of a given cell refers to. This may be specified using about URL .
table identifier
The table identifier is the id annotation on an annotated table . As defined in [ tabular-data-model ].
value URL
The value URL annotation on the current cell . As defined in [ tabular-data-model ].

4.2 Generating JSON

A conformant JSON conversion application MUST produce output conforming to this algorithm according to the chosen mode of conversion: standard or minimal .

Note

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

4.2.1 Minimal mode

The steps in the algorithm defined here apply to minimal mode.

  1. Insert an empty array A into the JSON output. The objects containing the name-value pairs associated with the cell values will be subsequently inserted into this array .

  2. Each table is processed sequentially in the order they are referenced in the group of tables . For each table where the suppress output annotation is false :

    1. Each row within the table is processed sequentially in order. For each row in the current table :

      1. Generate a sequence of objects , S 1 to S n , each of which corresponds to a subject described by the current row , as described in 4.3 Generating Objects .

        Note

        The subject(s) described by each row are determined according to the about URL annotation for each cell in the current row . Where about URL is undefined, a default subject for the row is used.

      2. As described in 4.4 Generating Nested Objects , process the sequence of objects , S 1 to S n , to produce a new sequence of root objects , S R 1 to S R m , that MAY include nested objects .

        Note

        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 .

      3. Insert each root object , S R 1 to S R m , into array A .

4.2.2 Standard mode

The steps in the algorithm defined here apply to standard mode.

  1. Insert an empty object G into the JSON output which is associated with the group of tables .

  2. If the group of tables has an identifier I G ; insert the following name-value pair into object G :

    name
    @id
    value
    I G
  3. Insert any notes and non-core annotations specified for the group of tables into object G according to the rules provided in 5. JSON-LD to JSON .

  4. Insert the following name-value pair into object G :

    name
    table tables
    value
    A T

    where A T is an array into which the objects describing the annotated tables will be subsequently inserted.

  5. Each table is processed sequentially in the order they are referenced in the group of tables .

    For each table where the suppress output annotation is false :

    1. Insert an empty object T into the array A T to represent the table .

    2. If the table has an identifier I T ; insert the following name-value pair into object T :

      name
      @id
      value
      I T
    3. Specify the source tabular data file URL for the current table based on the url annotation; insert the following name-value pair into object T :

      name
      url
      value
      URL
    4. Insert any notes and non-core annotations specified for the table into object T according to the rules provided in 5. JSON-LD to JSON .

      Note

      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.

    5. Insert the following name-value pair into object T :

      name
      row
      value
      A R

      where A R is an array into which the objects describing the rows will be subsequently inserted.

    6. Each row within the table is processed sequentially in order. For each row in the current table :

      1. Insert an empty object R into the array A R to represent the row .

      2. Specify the row number n for the row ; insert the following name-value pair into object R :

        name
        rownum
        value
        n
      3. 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 , insert the following name-value pair into object R :

        name
        url
        value
        URL #row= n source
      4. Specify any titles for the row ; if row titles is not null , insert the following name-value pair into object R :

        name
        titles
        value
        t

        where t is the single value or array of values provided by the row titles annotation.

        Note

        JSON has no native support for expressing language information; therefore any such information associated with the row titles is ignored.

      5. Insert any non-core annotations specified for the row into object R according to the rules provided in 5. JSON-LD to JSON .

      6. Insert the following name-value pair into object R :

        name
        describes
        value
        A

        where A is an array . The objects containing the name-value pairs associated with the cell values will be subsequently inserted into this array .

      7. Generate a sequence of objects , S 1 to S n , each of which corresponds to a subject described by the current row , as described in 4.3 Generating Objects .

        Note

        The subject(s) described by each row are determined according to the about URL annotation for each cell in the current row . Where about URL is undefined, a default subject for the row is used.

      8. As described in 4.4 Generating Nested Objects , process the sequence of objects , S 1 to S n , to produce a new sequence of root objects , S R 1 to S R m , that MAY include nested objects .

        Note

        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 .

      9. Insert each root object , S R 1 to S R m , into array A .

4.3 Generating Objects

The steps in the algorithm defined here apply to both standard and minimal modes.

This algorithm generates a sequence of objects , S 1 to S n , each of which corresponds to a subject described by the current row . The algorithm inserts name-value pairs into S i depending on the cell values as outlined in the following steps.

  1. Determine the unique subjects for the current row . The subject(s) described by each row are determined according to the about URL annotation for each cell in the current row . A default subject for the row is used for any cells where about URL is undefined.

  2. For each subject that the current row describes where at least one of the cells that refers to that subject has a value or value URL that is not null , and is associated with a column where suppress output annotation is false :

    1. Create an empty object S i to represent the subject i .

      ( i is the index number with values from 1 to n , where n is the number of subjects for the row )

      Subject i is identified according to the about URL annotation of its associated cells : I S . For a default subject where about URL is not specified by its cells , I S is null .

    2. If the identifier for subject i , I S , is not null , then insert the following name-value pair into object S i :

      name
      @id
      value
      I S
    3. Each cell referring to subject i is then processed sequentially according to the order of the columns .

      For each cell referring to subject i , where the suppress output annotation for the column associated with that cell is false , insert a name-value pair into object S i as described below:

      1. If the value of property URL for the cell is not null , then name N takes the value of property URL compacted according to the rules as defined in URL Compaction in [ tabular-metadata ].

        Else, name N takes the URI decoded value of the name annotation for the column associated with the cell . (URI decoding is necessary as name may have been encoded if it was taken from a supplied title.)

      2. If the value URL for the current cell is not null , then insert the following name-value pair into object S i :

        name
        N
        value
        V url

        where V url is the value of value URL annotation for the current cell expressed as a string in the JSON output. If N is @type , compact V url according to the rules as defined in URL Compaction in [ tabular-metadata ].

      3. Else, if the cell value is a list that is not empty, then the cell value provides a sequence of values for inclusion within the JSON output; insert an array A v containing each value V of the sequence into object S i :

        name
        N
        value
        A v

        Each of the values V derived from the sequence MUST be expressed in the JSON output according to the datatype of V as defined below in section 4.5 Interpreting datatypes .

        Note

        Since arrays are implicitly ordered in JSON, the ordered annotation has no effect on the JSON output.

      4. Else, if the cell value is not null , then the cell value provides a single value V for inclusion within the JSON output; insert the following name-value pair into object S i :

        name
        N
        value
        V

        Value V derived from the cell values MUST be expressed in the JSON output according to the datatype of the value as defined in section 4.5 Interpreting datatypes .

    4. If name N occurs more than once within object S i , the name-value pairs from each occurrence of name N MUST be compacted to form a single name-value pair with name N and whose value is an array containing all values from each of those name-value pairs.

4.4 Generating Nested Objects

The steps in the algorithm defined herein apply to both standard and minimal modes.

Where the current row describes multiple subjects , it MAY be possible to organise the objects associated with those subjects such that some objects are nested within others; e.g. where the value URL annotation for one cell matches the about URL annotation for another cell in the same row . This algorithm considers a sequence of objects generated according to 4.3 Generating Objects , S 1 to S n , each of which corresponds to a subject described by the current row . It generates a new sequence of root objects , S R 1 to S R m , that MAY include nested objects .

Note

Where the current row describes only a single subject , this algorithm may be bypassed as no nesting is possible. In such a case, the root object S R 1 is identical to the original object S 1 .

Note

This nesting algorithm is based on the interrelationships between subjects described within a given row that are specified using the value URL annotation. Cell values expressing the identity of a subject in the current row (i.e., as a simple literal) will be ignored by this algorithm.

The algorithm uses the following terms:

child
If two vertices are connected in a tree , the one which is further away from the root of the tree is referred to as the child of the other.
descendant
A vertex N is a descendant of a vertex M if either N is the child M , or there are vertices V 1 ,…,V k , such that V 1 =M , V k =N , and V k+1 is a child of V k .
edge
One of the main constituents of graphs ; in such data structures edges are used to establish relationships among vertices . In the context of this algorithm, edges are expressed in JSON using a name-value pair whose value is another object or an array of objects .
forest
A collection of disjoint trees . For the purpose of this algorithm, the order of the trees are important, i.e., forests can also be viewed as a sequence of roots .
graph
Data structure consisting of vertices (or "nodes") and edges . See, for example, [ Knuth ] for further details.
node
Synonym of vertex .
root
A dedicated vertex in a tree ; a root is not the child of any vertex .
tree
A tree (or rooted tree ) is a connected, acyclic graph where one vertex has been designated as the root , in which case the edges have a natural orientation towards or away from the root .
vertex
One of the main constituents of graphs ; in such data structures a vertex usually holds further information or data. In the context of this algorithm, vertices are used to represent the JSON objects .

The nesting algorithm is defined as follows:

  1. For all cells in the current row , determine the value URLs , V url , that occur only once . The list of these uniquely occurring value URLs is referred to as the URL-list .

  2. Create an empty forest F . Vertices in the trees of this forest represent the subjects described by the current row .

  3. For each object S i in the sequence S 1 to S n :

    1. Determine the identity of object S i : I S . If present in object S i , the name-value pair with name @id provides the value of I S . Else, object S i is not explicitly identified and I S is null .

    2. Check whether there is a vertex N in forest F that represents object S i . If none of the existing vertices in forest F represent object S i , then insert a new tree into forest F whose root is a vertex N that represents object S i and has identity I S .

    3. For all cells associated with the current object S i (e.g. whose about URL annotation matches I S ):

      1. If the value URL annotation of the current cell is defined and its value, V url , appears in the URL-list , then check each of the other objects in the sequence S 1 to S n to determine if V url identifies one of those objects .

        For object S j , if the name-value pair with name @id is present and its value matches V url , then:

        1. If the root of the tree containing vertex N is a vertex that represents object S j , then object S i is already a descendant of object S j ; no further action should be taken for this instance of V url .

          Note

          This clause in the algorithm prevents circular loops being created.

          Furthermore, because the URL-list contains value URLs that occur only once for the current row , object S i cannot be a descendant of an intermediate vertices in the tree .

        2. Else, if there is a root vertex M in forest F that represents object S j , then set vertex M as a child of vertex N and remove vertex M from the list of roots in forest F (i.e., the tree rooted by M becomes a sub-tree of N ).

        3. Else, create a new vertex M that represents object S j as a child of vertex N .

  4. Each vertex in forest F represents an object in the original sequence of objects S 1 to S n and is associated with a subject described by the current row . Rearrange objects S 1 to S n such that they mirror the structure of the trees in forest F as follows: If vertex M , representing object S i , is a child of vertex N , representing object S j , then the name-value pair in object S j associated with the edge relating M and N MUST be modifed such that the (literal) value, V url , from that name-value pair is replaced by object S i thus creating a nested object .

    Note

    Objects represented by root vertices are referred to as root objects .

  5. Return the sequence of root objects , S R 1 to S R m .

Note

An implementation may be able to optimize the algorithm by skipping branches (e.g. if URL-list is empty) or by other means.

4.5 Interpreting datatypes

Cell values are expressed in the JSON output according to the cell value's datatype . The relationship between the base annotation value of the cell value's datatype and the primitive types supported by JSON (as specified in [ RFC7159 ]) is provided in the table below.

Note

Instances of JSON reserved characters within string values MUST be escaped as defined in [ RFC7159 ].

JSON has no native support for expressing language information; therefore the language of a value has no effect on the JSON output.

Note

Only the base annotation value is used to determine the primitive type used wihtin the JSON output. Additional restrictions to the cell value's datatype , such as the id annotation, are ignored for the purposes of conversion to JSON.

Note

A datatype's format 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 JSON primitive type
anyAtomicType string
anyURI string
base64Binary string
boolean boolean
date string
dateTime string
dateTimeStamp string
decimal number
integer number
long number
int number
short number
byte number
nonNegativeInteger number
positiveInteger number
unsignedLong number
unsignedInt number
unsignedShort number
unsignedByte number
nonPositiveInteger number
negativeInteger number
double number
duration string
dayTimeDuration string
yearMonthDuration string
float number
gDay string
gMonth string
gMonthDay string
gYear string
gYearMonth string
hexBinary string
QName string
string string
normalizedString string
token string
language string
Name string
NMTOKEN string
xml string
html string
json string
time string

5. JSON-LD to JSON

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

Note

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.

Name-value pairs from notes and non-core annotations annotations are generally copied verbatim from the metadata description subject to the exceptions below:

  1. Name-value pairs whose value is an object using the [ json-ld ] keyword @value , for example:

    name
    N
    value
    { "@value": " V " }

    are transformed to:

    name
    N
    value
    V

    Name-value pairs occurring within the value object that use [ json-ld ] keywords @language and @type are ignored.

  2. Name-value pairs whose value is an object using the [ json-ld ] keyword @id to coerce a string-value to be interpreted as an IRI, for example:

    name
    N
    value
    { "@id": " V url " }

    are transformed to:

    name
    N
    value
    V url

In addition to compacting values of property URLs , URLs which ware the value of @type used within the notes and non-core annotations are compacted according to the rules as defined in URL Compaction in [ tabular-metadata ].

6. Examples

This section is non-normative.

Note

Each of the examples expresses more complex conversions - it is recommended that readers of this specification work through the examples in sequential order.

6.1 Simple example

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:

Example 2: http://example.org/countries.csv
countryCode,latitude,longitude,name
AD,42.546245,1.601554,Andorra
AE,23.424076,53.847818,"United Arab Emirates"
AF,33.93911,67.709953,Afghanistan

AD,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 JSON.

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 "42.546245" "42.5" "42.546245" "42.5" null
C1.3 T C3 R1 "1.601554" "1.6" "1.601554" "1.6" null
C1.4 T C4 R1 "Andorra" "Andorra" null
C2.1 T C1 R2 "AE" "AE" null
C2.2 T C2 R2 "23.424076" "23.4" "23.424076" "23.4" null
C2.3 T C3 R2 "53.847818" "53.8" "53.847818" "53.8" 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 "33.93911" "33.9" "33.93911" "33.9" null
C3.3 T C3 R3 "67.709953" "67.7" "67.709953" "67.7" null
C3.4 T C4 R3 "Afghanistan" "Afghanistan" null

Minimal mode output for this example is provided below:

Example 3: http://example.org/countries-minimal.json
[{ 
  "countryCode": "AD", 
   
   

  "latitude": "42.5", 
  "longitude": "1.6", 
  "name": "Andorra" 
}, { 
  "countryCode": "AE", 
   
   

  "latitude": "23.4", 
  "longitude": "53.8", 
  "name": "United Arab Emirates" 
}, { 
  "countryCode": "AF", 
   
   

  "latitude": "33.9", 
  "longitude": "67.7", 
  "name": "Afghanistan" 


}]

Note

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 and so the name-value pairs associated with the cell values of that row occur within the same object .

Given that the property URL is null for cells in table T ( { "url": "http://example.org/countries.csv"} ), the simplified name is used in the name-value pairs; e.g. countryCode rather than http://example.org/countries.csv#countryCode

Standard mode output for this example is provided below:

Example 4: http://example.org/countries-standard.json
{
  "tables": [{
    "url": "http://example.org/countries.csv",
    "row": [{
      "url": "http://example.org/countries.csv#row=2",
      "rownum": 1,
      "describes": [{ 
        "countryCode": "AD", 
         
         

        "latitude": "42.5", 
        "longitude": "1.6", 
        "name": "Andorra" 
      }]
    }, {
      "url": "http://example.org/countries.csv#row=3",
      "rownum": 2,
      "describes": [{ 
        "countryCode": "AE", 
         
         

        "latitude": "23.4", 
        "longitude": "53.8", 
        "name": "United Arab Emirates"
      }]
    }, {
      "url": "http://example.org/countries.csv#row=4",
      "rownum": 3,
      "describes": [{  
        "countryCode": "AF", 
         
         

        "latitude": "33.9", 
        "longitude": "67.7", 
        "name": "Afghanistan" 
      }]
    }]
  }]


}

Note

Even though the table was defined in isolation, the annotated table is wrapped in a group of tables .

The name-value pair with name url provides reference to the original tabular data file and to specific rows therein.

The row number is provided for each row using name-value pair with name rownum .

The object containing the name-values pairs associated with the cell values of a row are related to the object for that row using the name-value pair with name describes .

6.2 Example with single table and rich annotations

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:

Example 5: http://example.org/tree-ops-ext.csv
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>"
Example 6: http://example.org/tree-ops-ext.csv-metadata.json
{
  "@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}"
  }


}

Note

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

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"
Note

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

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>
Note

The lists of values from cells in column C7 ( "name": "comments" ) are assumed to be unordered as the boolean ordered annotation, which defaults to false , has not be set within the metadata description.

Minimal mode output for this example is provided below:

Example 7: http://example.org/tree-ops-ext-minimal.json
[{
  "@id": "http://example.org/tree-ops-ext#gid-1",
  "on_street": "ADDISON AV",
  "species": "Celtis australis",
  "trim_cycle": "Large Tree Routine Prune",
  "dbh": 11,
  "inventory_date": "2010-10-18",
  "protected": false,
  "kml": "<Point><coordinates>-122.156485,37.440963</coordinates></Point>"
}, {
  "@id": "http://example.org/tree-ops-ext#gid-2",
  "on_street": "EMERSON ST",
  "species": "Liquidambar styraciflua",
  "trim_cycle": "Large Tree Routine Prune",
  "dbh": 11,
  "inventory_date": "2010-06-02",
  "protected": false,
  "kml": "<Point><coordinates>-122.156749,37.440958</coordinates></Point>"
}, {
  "@id": "http://example.org/tree-ops-ext#gid-6",
  "on_street": "ADDISON AV",
  "species": "Robinia pseudoacacia",
  "trim_cycle": "Large Tree Routine Prune",
  "dbh": 29,
  "inventory_date": "2010-06-01",
  "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>"


}]

Note

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 column suppress output annotation is true .

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 a sequence of values; the set of values are included in an array .

Standard mode output for this example is provided below:

Example 8: http://example.org/tree-ops-ext-standard.json
{
  "tables": [{
    "@id": "http://example.org/tree-ops-ext",
    "url": "http://example.org/tree-ops-ext.csv",
    "dc:title": "Tree Operations",
    "dcat:keyword": [ "tree", "street", "maintenance" ],
    "dc:publisher": [{
      "schema:name": "Example Municipality",
      "schema:url": "http://example.org"
    }],
    "dc:license": "http://opendefinition.org/licenses/cc-by/",
    "dc:modified": "2010-12-31",
    "notes": [{
      "@type": "oa:Annotation",
      "oa:hasTarget": "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": "text/plain"
      }
    }],
    "row": [{
      "url": "http://example.org/tree-ops-ext.csv#row=2",
      "rownum": 1,
      "describes": [{ 
        "@id": "http://example.org/tree-ops-ext#gid-1",
        "on_street": "ADDISON AV",
        "species": "Celtis australis",
        "trim_cycle": "Large Tree Routine Prune",
        "dbh": 11,
        "inventory_date": "2010-10-18",
        "protected": false,
        "kml": "<Point><coordinates>-122.156485,37.440963</coordinates></Point>"
      }]
    }, {
      "url": "http://example.org/tree-ops-ext.csv#row=3",
      "rownum": 2,
      "describes": [{ 
        "@id": "http://example.org/tree-ops-ext#gid-2",
        "on_street": "EMERSON ST",
        "species": "Liquidambar styraciflua",
        "trim_cycle": "Large Tree Routine Prune",
        "dbh": 11,
        "inventory_date": "2010-06-02",
        "protected": false,
        "kml": "<Point><coordinates>-122.156749,37.440958</coordinates></Point>"
      }]
    }, {
      "url": "http://example.org/tree-ops-ext.csv#row=4",
      "rownum": 3,
      "describes": [{  
        "@id": "http://example.org/tree-ops-ext#gid-6",
        "on_street": "ADDISON AV",
        "species": "Robinia pseudoacacia",
        "trim_cycle": "Large Tree Routine Prune",
        "dbh": 29,
        "inventory_date": "2010-06-01",
        "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>"
      }]
    }]
  }]


}

Note

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.

6.3 Example with single table and using virtual columns to produce multiple subjects per row

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:

Example 9: http://example.org/events-listing.csv
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
Example 10: http://example.org/events-listing.csv-metadata.json
{
  "@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}"
    }]
  }


}

Note

The CSV to JSON 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 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 JSON 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 JSON.

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:

id core annotations
table number source number cells name titles virtual
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 below:

Example 11: http://example.org/events-listing-minimal.json
[{
  "@id": "http://example.org/events-listing.csv#event-1",
  "@type": "schema:MusicEvent",
  "schema:name": "B.B. King",
  "schema:startDate": "2014-04-12T19:30:00",
  "schema:location": {
    "@id": "http://example.org/events-listing.csv#place-1",
    "@type": "schema:Place",
    "schema:name": "Lupo’s Heartbreak Hotel",
    "schema:address": "79 Washington St., Providence, RI"
  },
  "schema:offer": {
    "@id": "http://example.org/events-listing.csv#offer-1",
    "@type": "schema:Offer",
    "schema:offer": "https://www.etix.com/ticket/1771656"
  }
}, {
  "@id": "http://example.org/events-listing.csv#event-2",
  "@type": "schema:MusicEvent",
  "schema:name": "B.B. King",
  "schema:startDate": "2014-04-13T20:00:00",
  "schema:location": {
    "@id": "http://example.org/events-listing.csv#place-2",
    "@type": "schema:Place",
    "schema:name": "Lynn Auditorium",
    "schema:address": "Lynn, MA, 01901"
  },
  "schema:offer": {
    "@id": "http://example.org/events-listing.csv#offer-2",
    "@type": "schema:Offer",
    "schema:offer": "http://frontgatetickets.com/venue.php?id=11766"
  }


}]

Note

Three resources are defined for each row within the table; event, location and offer. Therefore three objects are created for each row .

Each column description 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—noting that the use of rdf:type is converted to the name @type (as used in [ json-ld ]) by this conversion application.

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

Example 12: http://example.org/events-listing-standard.json
{
  "tables": [{
    "url": "http://example.org/events-listing.csv",
    "row": [{
      "url": "http://example.org/events-listing.csv#row=2",
      "rownum": 1,
      "describes": [{ 
        "@id": "http://example.org/events-listing.csv#event-1",
        "@type": "schema:MusicEvent",
        "schema:name": "B.B. King",
        "schema:startDate": "2014-04-12T19:30:00",
        "schema:location": {
          "@id": "http://example.org/events-listing.csv#place-1",
          "@type": "schema:Place",
          "schema:name": "Lupo’s Heartbreak Hotel",
          "schema:address": "79 Washington St., Providence, RI"
        },
        "schema:offers": {
          "@id": "http://example.org/events-listing.csv#offer-1",
          "@type": "schema:Offer",
          "schema:url": "https://www.etix.com/ticket/1771656"
        }
      }]
    }, {
      "url": "http://example.org/events-listing.csv#row=3",
      "rownum": 2,
      "describes": [{ 
        "@id": "http://example.org/events-listing.csv#event-2",
        "@type": "schema:MusicEvent",
        "schema:name": "B.B. King",
        "schema:startDate": "2014-04-13T20:00:00",
        "schema:location": {
          "@id": "http://example.org/events-listing.csv#place-2",
          "@type": "schema:Place",
          "schema:name": "Lynn Auditorium",
          "schema:address": "Lynn, MA, 01901"
        },
        "schema:offers": {
          "@id": "http://example.org/events-listing.csv#offer-2",
          "@type": "schema:Offer",
          "schema:url": "http://frontgatetickets.com/venue.php?id=11766"
        }
      }]
    }]
  }]


}

Note

The resources described by each row are explicitly defined using the about URL annotation—in this case three resources per row (event, location, and offer). The objects containing the name-values pairs associated with the cell values of a row are related to the object for each subject in that row using the name-value pair with name describes .

6.4 Example with table group comprising four interrelated tables

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:

Example 13: http://example.org/gov.uk/data/organizations.csv
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
Example 14: http://example.org/gov.uk/data/professions.csv
Profession
Finance
Information Technology
Operational Delivery
Policy
Example 15: http://example.org/senior-roles.csv
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
Example 16: http://example.org/junior-roles.csv
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
Example 17: http://example.org/csv-metadata.json
{
  "@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"
  }]


}

Example 18: http://example.org/gov.uk/schema/organizations.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"
    }
  }]


}

Example 19: http://example.org/gov.uk/schema/professions.json
{
  "@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"


}

Example 20: http://example.org/gov.uk/schema/senior-roles.json
{
  "@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"
    }
  }]


}

Example 21: http://example.org/gov.uk/schema/junior-roles.json
{
  "@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"
    }
  }]


}

Note

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

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
Note

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
Note

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>
Note

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

Example 22: http://example.org/public-sector-roles-and-salaries-minimal.json
[{
  "@id": "http://example.org/organization/hefce.ac.uk/post/90115",
  "dc:identifier": "90115",
  "org:heldBy": {
    "@id": "http://example.org/organization/hefce.ac.uk/person/1",
    "foaf:name": "Steve Egan"
  },
  "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"
}, {
  "@id": "http://example.org/organization/hefce.ac.uk/post/90334",
  "dc:identifier": "90334",
  "org:heldBy": {
    "@id": "http://example.org/organization/hefce.ac.uk/person/2",
    "foaf:name": "Sir Alan Langlands"
  },
  "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"
}, {
  "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,
  "http://example.org/gov.uk/def/max_pay": 20002,
  "http://example.org/gov.uk/def/job": "Administrator",
  "http://example.org/gov.uk/def/number_of_posts": 8.67,
  "http://example.org/gov.uk/def/profession": "Operational Delivery",
  "org:postIn": "http://example.org/organization/hefce.ac.uk"
}, {
  "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,
  "http://example.org/gov.uk/def/max_pay": 22478,
  "http://example.org/gov.uk/def/job": "Administrator",
  "http://example.org/gov.uk/def/number_of_posts": 0.5,
  "http://example.org/gov.uk/def/profession": "Operational Delivery",
  "org:postIn": "http://example.org/organization/hefce.ac.uk"


}]

Note

Prefixes defined within the RDFa 1.1 Initial Context ([ rdfa-core ]) are not expanded; e.g. dc: for <http://purl.org/dc/terms/>.

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 has the value true for each of the tables .

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. However, since senior posts and junior posts are described in different tables it is not possible to create nested objects for this particular case.

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. The person object provides the value of the name-value pair with corresponding name org:heldBy , thus nesting the person object within the post object .

Standard mode output for this example is provided below:

Example 23: http://example.org/public-sector-roles-and-salaries-standard.json
{
  "tables": [{
    "url": "http://example.org/senior-roles.csv",
    "row": [{
      "url": "http://example.org/senior-roles.csv#row=2",
      "rownum": 1,
      "describes": [{ 
        "@id": "http://example.org/organization/hefce.ac.uk/post/90115",
        "dc:identifier": "90115",
        "org:heldBy": {
          "@id": "http://example.org/organization/hefce.ac.uk/person/1",
          "foaf:name": "Steve Egan"
        },
        "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"
      }]
    }, {
      "url": "http://example.org/senior-roles.csv#row=3",
      "rownum": 2,
      "describes": [{ 
        "@id": "http://example.org/organization/hefce.ac.uk/post/90334",
        "dc:identifier": "90334",
        "org:heldBy": {
          "@id": "http://example.org/organization/hefce.ac.uk/person/2",
          "foaf:name": "Sir Alan Langlands"
        },
        "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"
      }]
    }]
  }, {
    "url": "http://example.org/junior-roles.csv",
    "row": [{
      "url": "http://example.org/junior-roles.csv#row=2",
      "rownum": 1,
      "describes": [{ 
        "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,
        "http://example.org/gov.uk/def/max_pay": 20002,
        "http://example.org/gov.uk/def/job": "Administrator",
        "http://example.org/gov.uk/def/number_of_posts": 8.67,
        "http://example.org/gov.uk/def/profession": "Operational Delivery",
        "org:postIn": "http://example.org/organization/hefce.ac.uk"
      }]
    }, {
      "url": "http://example.org/junior-roles.csv#row=3",
      "rownum": 2,
      "describes": [{ 
        "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,
        "http://example.org/gov.uk/def/max_pay": 22478,
        "http://example.org/gov.uk/def/job": "Administrator",
        "http://example.org/gov.uk/def/number_of_posts": 0.5,
        "http://example.org/gov.uk/def/profession": "Operational Delivery",
        "org:postIn": "http://example.org/organization/hefce.ac.uk"
      }]
    }]
  }]


}

A. Acknowledgements

At the time of publication, the following individuals had participated in the Working Group, in the order of their first name: Adam Retter, Alf Eaton, Anastasia Dimou, Andy Seaborne, Axel Polleres, Christopher Gutteridge, Dan Brickley, Davide Ceolin, Eric Stephan, Erik Mannens, Gregg Kellogg, Ivan Herman, Jeni Tennison, Jeremy Tandy, Jürgen Umbrich, Rufus Pollock, Stasinos Konstantopoulos, William Ingram, and Yakov Shafranovich.

B. Changes since previous versions

B.1 Changes since the working draft of 16 April 2015

B.2 Changes since the first public working draft of 08 January 2015

The document has undergone substantial changes since the first public working draft . Below are some of the changes made:

C. References

C.1 Normative references

[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels . March 1997. Best Current Practice. URL: https://tools.ietf.org/html/rfc2119
[RFC7159]
T. Bray, Ed.. The JavaScript Object Notation (JSON) Data Interchange Format . March 2014. Proposed Standard. URL: https://tools.ietf.org/html/rfc7159
[csv2rdf]
Jeremy Tandy; Ivan Herman; Gregg Kellogg. Generating RDF from Tabular Data on the Web . W3C Working Draft. URL: http://www.w3.org/TR/2015/WD-csv2rdf-20150416/ http://www.w3.org/TR/2015/CR-csv2rdf-20150716/
[rdf11-concepts]
Richard Cyganiak; David Wood; Markus Lanthaler. RDF 1.1 Concepts and Abstract Syntax . 25 February 2014. W3C Recommendation. URL: http://www.w3.org/TR/rdf11-concepts/
[tabular-data-model]
Jeni Tennison; Gregg Kellogg. Model for Tabular Data and Metadata on the Web . W3C Working Draft. URL: http://www.w3.org/TR/2015/WD-tabular-data-model-20150416/ http://www.w3.org/TR/2015/CR-tabular-data-model-20150716/
[tabular-metadata]
Jeni Tennison; Gregg Kellogg. Metadata Vocabulary for Tabular Data . W3C Working Draft. URL: http://www.w3.org/TR/2015/WD-tabular-metadata-20150416/ http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/

C.2 Informative references

[Knuth]
The Art of Computer Programming Volume 1: Fundamental Algorithms (3rd ed.) .
[RFC6761]
S. Cheshire; M. Krochmal. Special-Use Domain Names . February 2013. Proposed Standard. URL: https://tools.ietf.org/html/rfc6761
[RFC7111]
M. Hausenblas; E. Wilde; J. Tennison. URI Fragment Identifiers for the text/csv Media Type . January 2014. Informational. URL: https://tools.ietf.org/html/rfc7111
[UAX15]
Mark Davis; Ken Whistler. Unicode Normalization Forms . 31 August 2012. Unicode Standard Annex #15. URL: http://www.unicode.org/reports/tr15
[json-ld]
Manu Sporny; Gregg Kellogg; Markus Lanthaler. JSON-LD 1.0 . 16 January 2014. W3C Recommendation. URL: http://www.w3.org/TR/json-ld/
[rdfa-core]
Ben Adida; Mark Birbeck; Shane McCarron; Ivan Herman et al. RDFa Core 1.1 - Third Edition . 17 March 2015. W3C Recommendation. URL: http://www.w3.org/TR/rdfa-core/