delete: <html lang="en" dir="ltr" typeof="bibo:Document w3p:CR" prefix="bibo: http://purl.org/ontology/bibo/ w3p: http://www.w3.org/2001/02pd/rec54#"> insert: <html lang="en" dir="ltr" typeof="bibo:Document w3p:PR" prefix="bibo: http://purl.org/ontology/bibo/ w3p: http://www.w3.org/2001/02pd/rec54#"> Model for Tabular Data and Metadata on the Web insert: <style type="text/css"> insert: <style type="text/css"> delete: <link rel="stylesheet" href="https://www.w3.org/StyleSheets/TR/W3C-CR"> delete: <style type="text/css"> delete: </style> insert: <link rel="stylesheet" href="https://www.w3.org/StyleSheets/TR/W3C-PR"> insert: <script id="initialUserConfig" type="application/json"> delete: <body class="h-entry" data-feedly-mini="yes" role="document" id="respecDocument"> insert: <body class="h-entry" role="document" id="respecDocument">

Abstract

Tabular data is routinely transferred on the web in a variety of formats, including variants on CSV, tab-delimited files, fixed field formats, spreadsheets, HTML tables, and SQL dumps. This document outlines a data model, or infoset, for tabular data and metadata about that tabular data that can be used as a basis for validation, display, or creating other formats. It also contains some non-normative guidance for publishing tabular data as CSV and how that maps into the tabular data model.

An annotated model of tabular data can be supplemented by separate metadata about the table. This specification defines how implementations should locate that metadata, given a file containing tabular data. The standard syntax for that metadata is defined in [ tabular-metadata ]. Note, however, that applications may have other means to create annotated tables, e.g., through some application specific API-s; this model does not depend on the specificities described in [ tabular-metadata ].

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 insert: <a href="http://www.w3.org/2013/csvw"> CSV on the Web Working Group insert: </a> was insert: <a href="http://www.w3.org/2013/05/lcsv-charter.html"> chartered insert: </a> to produce a Recommendation recommendation "Access methods for CSV Metadata" as well as Recommendations recommendations for "Metadata vocabulary for CSV data" and "Mapping mechanism to transforming CSV into various Formats formats (e.g., RDF, JSON, or XML)". This document aims to primarily satisfy the first of those Recommendations "Access methods for CSV Metadata" recommendation (see section 5. Locating Metadata ), though it also specifies an underlying model for tabular data and is therefore a basis for the other chartered Recommendations.

This definition of CSV used in this document is based on IETF's [ RFC4180 ] which is an Informational RFC. The working group's expectation is that future suggestions to refine RFC 4180 will be relayed to the IETF (e.g. around encoding and line endings) and contribute to its discussions about moving CSV to the Standards track.

Many files containing tabular data embed metadata, for example in lines before the header row of an otherwise standard CSV document. This specification does not define any formats for embedding metadata within CSV files, aside from the titles of columns in the header row which is defined in CSV. We would encourage groups that define tabular data formats to also define a mapping into the annotated tabular data model defined in this document.

This document was published by the CSV on the Web Working Group as a Candidate Proposed Recommendation. This document is intended to become a W3C Recommendation. If you wish to make The insert: <abbr title="World Wide Web Consortium"> W3C insert: </abbr> Membership and other interested parties are invited to review the document and send comments regarding this document, please send them to delete: <a href="mailto:public-csv-wg@w3.org"> to insert: <a rel="discussion" href="mailto:public-csv-wg@w3.org"> public-csv-wg@w3.org ( subscribe , archives ). delete: <abbr title="World Wide Web Consortium"> W3C delete: </abbr> publishes a Candidate Recommendation to indicate ) through 15 December 2015. Advisory Committee Representatives should consult their insert: <a href="https://www.w3.org/2002/09/wbs/myQuestionnaires"> WBS questionnaires insert: </a> . Note that the document is believed to be stable and to encourage implementation by the developer community. This Candidate Recommendation is substantive technical comments were expected to advance to Proposed Recommendation no earlier than during the Last Call review period that ended 30 October 2015. All comments are welcome.

Please see the Working Group's delete: <a href="http://www.w3.org/2013/csvw/tests/reports/index.html"> insert: <a href="http://www.w3.org/2013/csvw/implementation_report.html"> implementation report .

Publication as a Candidate Proposed 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 delete: <a id="w3c_process_revision" href="http://www.w3.org/2014/Process-20140801/"> insert: <a id="w3c_process_revision" href="http://www.w3.org/2015/Process-20150901/"> 1 August 2014 September 2015 W3C Process Document .

Table of Contents

delete: <ul class="toc" role="directory" id="respecContents"> insert: <ul class="toc" role="directory">

1. Introduction

delete: <dfn title="tabular data" id="dfn-tabular-data"> insert: <dfn data-dfn-type="dfn" id="dfn-tabular-data"> Tabular data is data that is structured into rows, each of which contains information about some thing. Each row contains the same number of cells (although some of these cells may be empty), which provide values of properties of the thing described by the row. In tabular data, cells within the same column provide values for the same property of the things described by each row. This is what differentiates tabular data from other line-oriented formats.

Tabular data is routinely transferred on the web in a textual format called CSV, but the definition of CSV in practice is very loose. Some people use the term to mean any delimited text file. Others stick more closely to the most standard definition of CSV that there is, [ RFC4180 ]. Appendix A describes the various ways in which CSV is defined. This specification refers to such files, as well as tab-delimited files, fixed field formats, spreadsheets, HTML tables, and SQL dumps as delete: <dfn title="tabular data file" id="dfn-tabular-data-file"> insert: <dfn data-dfn-type="dfn" id="dfn-tabular-data-files"> tabular data files .

In section 4. Tabular Data Models , this document defines a model for tabular data that abstracts away from the varying syntaxes that are used for when exchanging tabular data. The model includes annotations, or metadata, about collections of individual tables, rows, columns, and cells. These annotations are typically supplied through separate metadata files; section 5. Locating Metadata defines how these metadata files can be located, while [ tabular-metadata ] defines what they contain.

Once an delete: <a href="#dfn-annotated-table" class="internalDFN"> insert: <a href="#dfn-annotated-table" class="internalDFN" data-link-type="dfn"> annotated table has been created, it can be processed in various ways, such as display, validation, or conversion into other formats. This processing is described in section 6. Processing Tables .

This specification does not normatively define a format for exchanging tabular data. However, it does provide some best practice guidelines for publishing tabular data as CSV, in section section 7. Best Practice CSV , and for parsing both this syntax and those similar to it, in section 8. Parsing Tabular Data .

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 , MUST , MUST NOT , SHOULD , and SHOULD NOT are to be interpreted as described in [ RFC2119 ].

This specification makes use of the delete: <dfn title="compact IRI" id="dfn-compact-iri"> insert: <dfn data-dfn-type="dfn" id="dfn-compact-iri-syntax"> 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#
dc :
http://purl.org/dc/terms/
rdf :
http://www.w3.org/1999/02/22-rdf-syntax-ns#
rdfs :
http://www.w3.org/2000/01/rdf-schema#
schema :
http://schema.org/
xsd :
http://www.w3.org/2001/XMLSchema#

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.
delete: <dfn id="dfn-definition"> insert: <dfn data-dfn-type="dfn" id="dfn-definition"> definition
A definition of a term, to be used elsewhere in this or other specifications, is in bold and italics.
delete: <a title="definition" href="#dfn-definition" class="internalDFN"> insert: <a data-lt="definition" href="#dfn-definition" class="internalDFN" data-link-type="dfn"> definition reference
A reference to a definition in this document is underlined and is also an active link to the definition itself.
delete: <a title="definition" href="#dfn-definition" class="internalDFN"> insert: <a data-lt="definition" href="#dfn-definition" class="internalDFN" data-link-type="dfn"> 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] delete: </a> reference insert: </a> ]
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. Tabular Data Models

This section defines an delete: <dfn id="dfn-annotated-tabular-data-model"> insert: <dfn data-dfn-type="dfn" id="dfn-annotated-tabular-data-model"> annotated tabular data model : a model for tables that are annotated with metadata. delete: <dfn title="annotation" id="dfn-annotation"> insert: <dfn data-dfn-type="dfn" id="dfn-annotations"> Annotations provide information about the cells, rows, columns, tables, and groups of tables with which they are associated. The delete: <dfn title="annotation value" id="dfn-annotation-value"> insert: <dfn data-dfn-type="dfn" id="dfn-values"> values of these annotations may be lists, structured objects, or atomic values. delete: <dfn id="dfn-core-annotations"> insert: <dfn data-dfn-type="dfn" id="dfn-core-annotations"> Core annotations are those that affect the behavior of processors defined in this specification, but other annotations may also be present on any of the components of the model.

Annotations may be described directly in [ tabular-metadata ], be embedded in a delete: <a href="#dfn-tabular-data-file" class="internalDFN"> insert: <a href="#dfn-tabular-data-files" class="internalDFN" data-link-type="dfn"> tabular data file , or created during the process of generating an delete: <a href="#dfn-annotated-table" class="internalDFN"> insert: <a href="#dfn-annotated-table" class="internalDFN" data-link-type="dfn"> annotated table .

String values within the tabular data model (such as column titles or cell string values) MUST contain only Unicode characters.

Note

In this document, the term delete: <a href="#dfn-annotation" class="internalDFN"> insert: <a href="#dfn-annotations" class="internalDFN" data-link-type="dfn"> annotation refers to any metadata associated with an object in the annotated tabular data model. These are not necessarily web annotations in the sense of [ annotation-model ].

4.1 Table groups

A delete: <dfn id="dfn-group-of-tables"> insert: <dfn data-dfn-type="dfn" id="dfn-group-of-tables"> group of tables comprises a set of delete: <a title="annotated table" href="#dfn-annotated-table" class="internalDFN"> insert: <a href="#dfn-annotated-table" class="internalDFN" data-link-type="dfn"> annotated tables and a set of annotations that relate to that group of tables. The delete: <a href="#dfn-core-annotations" class="internalDFN"> insert: <a href="#dfn-core-annotations" class="internalDFN" data-link-type="dfn"> core annotations of a group of tables are:

Groups of tables MAY in addition have any number of delete: <a title="annotation" href="#dfn-annotation" class="internalDFN"> insert: <a href="#dfn-annotations" class="internalDFN" data-link-type="dfn"> annotations which provide information about the group of tables. Annotations on a group of tables may include:

When originating from [ tabular-metadata ], these annotations arise from delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dfn-common-property" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dfn-common-properties" class="externalDFN"> common properties defined on delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dfn-table-group-description" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dfn-table-group-description" class="externalDFN"> table group descriptions within metadata documents.

4.2 Tables

An delete: <dfn id="dfn-annotated-table"> insert: <dfn data-dfn-type="dfn" id="dfn-annotated-table"> annotated table is a delete: <dfn id="dfn-table"> insert: <dfn data-dfn-type="dfn" id="dfn-table"> table that is annotated with additional metadata. The delete: <a href="#dfn-core-annotations" class="internalDFN"> insert: <a href="#dfn-core-annotations" class="internalDFN" data-link-type="dfn"> core annotations of a table are:

The table MAY in addition have any number of other delete: <a title="annotation" href="#dfn-annotation" class="internalDFN"> insert: <a href="#dfn-annotations" class="internalDFN" data-link-type="dfn"> annotations . Annotations on a table may include:

When originating from [ tabular-metadata ], these annotations arise from delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dfn-common-property" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dfn-common-properties" class="externalDFN"> common properties defined on delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dfn-table-description" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dfn-table-description" class="externalDFN"> table descriptions within metadata documents.

4.3 Columns

A delete: <dfn id="dfn-column"> insert: <dfn data-dfn-type="dfn" id="dfn-column"> column represents a vertical arrangement of delete: <a title="cell" href="#dfn-cell" class="internalDFN"> insert: <a href="#dfn-cell" class="internalDFN" data-link-type="dfn"> cells within a delete: <a href="#dfn-table" class="internalDFN"> insert: <a href="#dfn-table" class="internalDFN" data-link-type="dfn"> table . The delete: <a href="#dfn-core-annotations" class="internalDFN"> insert: <a href="#dfn-core-annotations" class="internalDFN" data-link-type="dfn"> core annotations of a column are:

Note

Several of these annotations arise from delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dfn-inherited-property" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dfn-inherited-properties" class="externalDFN"> inherited properties that may be defined within metadata on delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dfn-table-group-description" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dfn-table-group-description" class="externalDFN"> table group , delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dfn-table-description" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dfn-table-description" class="externalDFN"> table or individual delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dfn-column-description" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dfn-column-description" class="externalDFN"> column descriptions.

Columns MAY in addition have any number of other delete: <a title="annotation" href="#dfn-annotation" class="internalDFN"> insert: <a href="#dfn-annotations" class="internalDFN" data-link-type="dfn"> annotations , such as a description. When originating from [ tabular-metadata ], these annotations arise from delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dfn-common-property" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dfn-common-properties" class="externalDFN"> common properties defined on delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dfn-column-description" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dfn-column-description" class="externalDFN"> column descriptions within metadata documents.

4.4 Rows

A delete: <dfn id="dfn-row"> insert: <dfn data-dfn-type="dfn" id="dfn-row"> row represents a horizontal arrangement of delete: <a title="cell" href="#dfn-cell" class="internalDFN"> insert: <a href="#dfn-cell" class="internalDFN" data-link-type="dfn"> cells within a delete: <a href="#dfn-table" class="internalDFN"> insert: <a href="#dfn-table" class="internalDFN" data-link-type="dfn"> table . The delete: <a href="#dfn-core-annotations" class="internalDFN"> insert: <a href="#dfn-core-annotations" class="internalDFN" data-link-type="dfn"> core annotations of a row are:

Rows MAY have any number of additional delete: <a title="annotation" href="#dfn-annotation" class="internalDFN"> insert: <a href="#dfn-annotations" class="internalDFN" data-link-type="dfn"> annotations . The annotations on a row provide additional metadata about the information held in the row, such as:

Neither this specification nor [ tabular-metadata ] defines a method to specify such annotations. Implementations MAY define a method for adding annotations to rows by interpreting delete: <a title="table notes" href="#dfn-table-notes" class="internalDFN"> insert: <a data-lt="table notes" href="#dfn-notes" class="internalDFN" data-link-type="dfn"> notes on the table.

4.5 Cells

A delete: <dfn id="dfn-cell"> insert: <dfn data-dfn-type="dfn" id="dfn-cell"> cell represents a cell at the intersection of a delete: <a href="#dfn-row" class="internalDFN"> insert: <a href="#dfn-row" class="internalDFN" data-link-type="dfn"> row and a delete: <a href="#dfn-column" class="internalDFN"> insert: <a href="#dfn-column" class="internalDFN" data-link-type="dfn"> column within a delete: <a href="#dfn-table" class="internalDFN"> insert: <a href="#dfn-table" class="internalDFN" data-link-type="dfn"> table . The delete: <a href="#dfn-core-annotations" class="internalDFN"> insert: <a href="#dfn-core-annotations" class="internalDFN" data-link-type="dfn"> core annotations of a cell are:

Note

There presence or absence of quotes around a value within a CSV file is a syntactic detail that is not reflected in the tabular data model. In other words, there is no distinction in the model between the second value in a,,z and the second value in a,"",z .

Note

Several of these annotations arise from or are constructed based on delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dfn-inherited-property" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dfn-inherited-properties" class="externalDFN"> inherited properties that may be defined within metadata on delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dfn-table-group-description" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dfn-table-group-description" class="externalDFN"> table group , delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dfn-table-description" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dfn-table-description" class="externalDFN"> table or delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dfn-column-description" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dfn-column-description" class="externalDFN"> column descriptions.

Cells MAY have any number of additional delete: <a title="annotation" href="#dfn-annotation" class="internalDFN"> insert: <a href="#dfn-annotations" class="internalDFN" data-link-type="dfn"> annotations . The annotations on a cell provide metadata about the value held in the cell, particularly when this overrides the information provided for the delete: <a href="#dfn-column" class="internalDFN"> insert: <a href="#dfn-column" class="internalDFN" data-link-type="dfn"> column and delete: <a href="#dfn-row" class="internalDFN"> insert: <a href="#dfn-row" class="internalDFN" data-link-type="dfn"> row that the cell falls within. Annotations on a cell might be:

Neither this specification nor [ tabular-metadata ] defines a method to specify such annotations. Implementations MAY define a method for adding annotations to cells by interpreting delete: <a title="table notes" href="#dfn-table-notes" class="internalDFN"> insert: <a data-lt="table notes" href="#dfn-notes" class="internalDFN" data-link-type="dfn"> notes on the table.

insert: <div class="note">
insert: <div class="note-title" aria-level="4" role="heading" id="h-note6">
insert: <span> Note insert: </span> insert: </div>
insert: <p class="">

Units of measure are not a built-in part of the tabular data model. However, they can be captured through insert: <a data-lt="table notes" href="#dfn-notes" class="internalDFN" data-link-type="dfn"> notes insert: </a> or included in the converted output of tabular data through defining insert: <a data-lt="datatype" href="#dfn-datatype" class="internalDFN" data-link-type="dfn"> datatypes insert: </a> with identifiers that indicate the unit of measure, using insert: <a data-lt="virtual column" href="#dfn-virtual-columns" class="internalDFN" data-link-type="dfn"> virtual columns insert: </a> to create nested data structures, or using common properties to specify Data Cube attributes as defined in [ insert: <cite> insert: <a class="bibref" href="#bib-vocab-data-cube"> vocab-data-cube insert: </a> insert: </cite> ]. insert: </p>

insert: </div>

4.6 Datatypes

Columns and delete: <a title="cell value" href="#dfn-cell-value" class="internalDFN"> insert: <a href="#dfn-value" class="internalDFN" data-link-type="dfn"> cell values within tables may be annotated with a delete: <dfn id="dfn-datatype"> insert: <dfn data-dfn-type="dfn" id="dfn-datatype"> datatype which indicates the type of the values obtained by parsing the delete: <a title="cell string value" href="#dfn-cell-string-value" class="internalDFN"> insert: <a data-lt="cell string value" href="#dfn-string-value" class="internalDFN" data-link-type="dfn"> string value of the cell.

Datatypes are based on a subset of those defined in [ xmlschema11-2 ]. The delete: <a href="#dfn-annotated-tabular-data-model" class="internalDFN"> insert: <a href="#dfn-annotated-tabular-data-model" class="internalDFN" data-link-type="dfn"> annotated tabular data model limits delete: <a title="cell value" href="#dfn-cell-value" class="internalDFN"> insert: <a href="#dfn-value" class="internalDFN" data-link-type="dfn"> cell values to have datatypes as shown on the diagram :

Built-in Datatype Hierarchy diagram
Fig. 1 Diagram showing the built-in datatypes, based on [ xmlschema11-2 ]; names in parentheses denote aliases to the [ xmlschema11-2 ] terms (see the diagram in SVG or PNG formats)

The delete: <a href="#dfn-core-annotations" class="internalDFN"> insert: <a href="#dfn-core-annotations" class="internalDFN" data-link-type="dfn"> core annotations of a datatype are:

If the delete: <a title="datatype id" href="#dfn-datatype-id" class="internalDFN"> insert: <a data-lt-nodefault="" data-lt="datatype id" href="#dfn-datatype-id" class="internalDFN" data-link-type="dfn"> id of a datatype is that of a built-in datatype, the values of the other core annotations listed above MUST be consistent with the values defined in [ xmlschema11-2 ] or above. For example, if the delete: <a title="datatype id" href="#dfn-datatype-id" class="internalDFN"> insert: <a data-lt="datatype id" href="#dfn-datatype-id" class="internalDFN" data-link-type="dfn"> id is xsd:integer then the delete: <a title="datatype base" href="#dfn-datatype-base" class="internalDFN"> insert: <a data-lt="datatype base" href="#dfn-base" class="internalDFN" data-link-type="dfn"> base must be xsd:decimal .

Datatypes MAY have any number of additional delete: <a title="annotation" href="#dfn-annotation" class="internalDFN"> insert: <a href="#dfn-annotations" class="internalDFN" data-link-type="dfn"> annotations . The annotations on a datatype provide metadata about the datatype such as title or description. These arise from delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dfn-common-property" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dfn-common-properties" class="externalDFN"> common properties defined on datatype descriptions within metadata documents, as defined in [ tabular-metadata ].

delete: <div class="note-title" aria-level="4" role="heading" id="h-note6"> insert: <div class="note-title" aria-level="4" role="heading" id="h-note7">
Note

The delete: <a title="datatype id" href="#dfn-datatype-id" class="internalDFN"> insert: <a data-lt="datatype id" href="#dfn-datatype-id" class="internalDFN" data-link-type="dfn"> id annotation may reference an XSD, OWL or other datatype definition, which is not used by this specification for validating column values, but may be useful for further processing.

4.6.1 Length Constraints

The delete: <a title="datatype length" href="#dfn-datatype-length" class="internalDFN"> insert: <a data-lt="datatype length" href="#dfn-length" class="internalDFN" data-link-type="dfn"> length , delete: <a title="datatype minimum length" href="#dfn-datatype-minimum-length" class="internalDFN"> insert: <a data-lt="datatype minimum length" href="#dfn-minimum-length" class="internalDFN" data-link-type="dfn"> minimum length and delete: <a title="datatype maximum length" href="#dfn-datatype-maximum-length" class="internalDFN"> insert: <a data-lt="datatype maximum length" href="#dfn-maximum-length" class="internalDFN" data-link-type="dfn"> maximum length annotations indicate the exact, minimum and maximum lengths for delete: <a title="cell value" href="#dfn-cell-value" class="internalDFN"> insert: <a href="#dfn-value" class="internalDFN" data-link-type="dfn"> cell values .

The length of a delete: <a title="cell value" href="#dfn-cell-value" class="internalDFN"> insert: <a data-lt="cell value" href="#dfn-value" class="internalDFN" data-link-type="dfn"> value is determined as defined in [ xmlschema11-2 ], namely as follows:

  • if the value is null , its length is zero.
  • if the value is a string or one of its subtypes, its length is the number of characters (ie [ UNICODE ] code points ) in the value.
  • if the value is of a binary type, its length is the number of bytes in the binary value.

If the delete: <a title="cell value" href="#dfn-cell-value" class="internalDFN"> insert: <a data-lt="cell value" href="#dfn-value" class="internalDFN" data-link-type="dfn"> value is a delete: <a title="cell value list" href="#dfn-cell-value-list" class="internalDFN"> insert: <a data-lt="cell value list" href="#dfn-list" class="internalDFN" data-link-type="dfn"> list , the constraint applies to each element of the list.

4.6.2 Value Constraints

The delete: <a title="datatype minimum" href="#dfn-datatype-minimum" class="internalDFN"> insert: <a data-lt="datatype minimum" href="#dfn-minimum" class="internalDFN" data-link-type="dfn"> minimum , delete: <a title="datatype maximum" href="#dfn-datatype-maximum" class="internalDFN"> insert: <a data-lt="datatype maximum" href="#dfn-maximum" class="internalDFN" data-link-type="dfn"> maximum , delete: <a title="datatype minimum exclusive" href="#dfn-datatype-minimum-exclusive" class="internalDFN"> insert: <a data-lt="datatype minimum exclusive" href="#dfn-minimum-exclusive" class="internalDFN" data-link-type="dfn"> minimum exclusive , and delete: <a title="datatype maximum exclusive" href="#dfn-datatype-maximum-exclusive" class="internalDFN"> insert: <a data-lt="datatype maximum exclusive" href="#dfn-maximum-exclusive" class="internalDFN" data-link-type="dfn"> maximum exclusive annotations indicate limits on delete: <a title="cell value" href="#dfn-cell-value" class="internalDFN"> insert: <a href="#dfn-value" class="internalDFN" data-link-type="dfn"> cell values . These apply to numeric, date/time, and duration types.

Validation of delete: <a title="cell value" href="#dfn-cell-value" class="internalDFN"> insert: <a href="#dfn-value" class="internalDFN" data-link-type="dfn"> cell values against these datatypes is as defined in [ xmlschema11-2 ]. If the delete: <a title="cell value" href="#dfn-cell-value" class="internalDFN"> insert: <a data-lt="cell value" href="#dfn-value" class="internalDFN" data-link-type="dfn"> value is a delete: <a title="cell value list" href="#dfn-cell-value-list" class="internalDFN"> insert: <a data-lt="cell value list" href="#dfn-list" class="internalDFN" data-link-type="dfn"> list , the constraint applies to each element of the list.

5. Locating Metadata

As described in section 4. Tabular Data Models , tabular data may have a number of annotations associated with it. Here we describe the different methods that can be used to locate metadata that provides those annotations.

In the methods of locating metadata described here, metadata is provided within a single document. The syntax of such documents is defined in [ tabular-metadata ]. Metadata is located using a specific order of precedence:

  1. metadata supplied by the user of the implementation that is processing the tabular data, see section 5.1 Overriding Metadata .
  2. metadata in a document linked to using a Link header associated with the delete: <a href="#dfn-tabular-data-file" class="internalDFN"> insert: <a href="#dfn-tabular-data-files" class="internalDFN" data-link-type="dfn"> tabular data file , see section 5.2 Link Header .
  3. metadata located through default paths which may be overridden by a site-wide location configuration, see delete: <a href="#site-wide-location-configuration" class="sectionRef sec-ref"> insert: <a href="#default-locations-and-site-wide-location-configuration" class="sectionRef sec-ref"> section 5.3 Default Locations and Site-wide Location Configuration .
  4. metadata embedded within the delete: <a href="#dfn-tabular-data-file" class="internalDFN"> insert: <a href="#dfn-tabular-data-files" class="internalDFN" data-link-type="dfn"> tabular data file itself, see section 5.4 Embedded Metadata .

Processors MUST use the first metadata found for processing a delete: <a href="#dfn-tabular-data-file" class="internalDFN"> insert: <a href="#dfn-tabular-data-files" class="internalDFN" data-link-type="dfn"> tabular data file by using overriding metadata, if provided. Otherwise processors MUST attempt to locate the first metadata document from the Link header or the metadata located through site-wide configuration. If no metadata is supplied or found, processors MUST use delete: <a href="#dfn-embedded-metadata" class="internalDFN"> insert: <a href="#dfn-embedding-metadata" class="internalDFN" data-link-type="dfn"> embedded metadata . If the metadata does not originate from the embedded metadata, delete: <a href="#dfn-validators" class="internalDFN"> insert: <a href="#dfn-validators" class="internalDFN" data-link-type="dfn"> validators MUST verify that the delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dfn-table-group-description" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dfn-table-group-description" class="externalDFN"> table group description within that metadata is delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#table-group-description-compatibility" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#table-group-description-compatibility" class="externalDFN"> compatible with that in the delete: <a href="#dfn-embedded-metadata" class="internalDFN"> insert: <a href="#dfn-embedding-metadata" class="internalDFN" data-link-type="dfn"> embedded metadata , as defined in [ tabular-metadata ]. insert: </p>

insert: <div class="note">
insert: <div class="note-title" aria-level="3" role="heading" id="h-note8">
insert: <span> Note insert: </span> insert: </div>
insert: <p class="">

When feasible, processors should start from a metadata file and publishers should link to metadata files directly, rather than depend on mechanisms outlined in this section for locating metadata from a tabular data file. Otherwise, if possible, publishers should provide a insert: <code> Link insert: </code> header on the tabular data file as described in insert: <a href="#link-header" class="sectionRef sec-ref"> section insert: <span class="secno"> 5.2 insert: </span> insert: <span class="sec-title"> Link Header insert: </span> insert: </a> . insert: </p>

insert: </div>
insert: <div class="note">
insert: <div class="note-title" aria-level="3" role="heading" id="h-note9">
insert: <span> Note insert: </span> insert: </div>
insert: <p class="">

If there is no site-wide location configuration, insert: <a href="#default-locations-and-site-wide-location-configuration" class="sectionRef sec-ref"> section insert: <span class="secno"> 5.3 insert: </span> insert: <span class="sec-title"> Default Locations and Site-wide Location Configuration insert: </span> insert: </a> specifies default URI patterns or paths to be used to locate metadata. insert: </p>

insert: </div>
insert: <p>

5.1 Overriding Metadata

Processors SHOULD provide users with the facility to provide their own metadata for delete: <a title="tabular data file" href="#dfn-tabular-data-file" class="internalDFN"> insert: <a data-lt="tabular data file" href="#dfn-tabular-data-files" class="internalDFN" data-link-type="dfn"> tabular data files that they process. This might be provided:

For example, a processor might be invoked with:

Example 2 : Command-line CSV processing with column types
 $ csvlint data.csv --datatypes:string,float,string,string 

to enable the testing of the types of values in the columns of a CSV file, or with:

Example 3 : Command-line CSV processing with a schema
 $ csvlint data.csv --schema:schema.json 

to supply a schema that describes the contents of the file, against which it can be validated.

Metadata supplied in this way is called overriding, or user-supplied, metadata. Implementations SHOULD define how any options they define are mapped into the vocabulary defined in [ tabular-metadata ]. If the user selects existing metadata files, implementations MUST NOT use metadata located through the Link header (as described in section 5.2 Link Header ) or site-wide location configuration (as described in delete: <a href="#site-wide-location-configuration" class="sectionRef sec-ref"> insert: <a href="#default-locations-and-site-wide-location-configuration" class="sectionRef sec-ref"> section 5.3 Default Locations and Site-wide Location Configuration ).

delete: <div class="note-title" aria-level="4" role="heading" id="h-note7"> insert: <div class="note-title" aria-level="4" role="heading" id="h-note10">
Note

Users should ensure that any metadata from those locations that they wish to use is explicitly incorporated into the overriding metadata that they use to process tabular data. Processors may provide facilities to make this easier by automatically merging metadata files from different locations, but this specification does not define how such merging is carried out.

delete: <section id="site-wide-location-configuration" typeof="bibo:Chapter" resource="#site-wide-location-configuration" property="bibo:hasPart"> delete: <h3 id="h-site-wide-location-configuration" resource="#h-site-wide-location-configuration"> insert: <section id="default-locations-and-site-wide-location-configuration" typeof="bibo:Chapter" resource="#default-locations-and-site-wide-location-configuration" property="bibo:hasPart">
insert: <h3 id="h-default-locations-and-site-wide-location-configuration" resource="#h-default-locations-and-site-wide-location-configuration">

5.3 Default Locations and Site-wide Location Configuration

If the user has not supplied a metadata file as overriding metadata, described in section 5.1 Overriding Metadata , and no applicable metadata file has been discovered through a Link header, described in section 5.2 Link Header , processors MUST attempt to locate a metadata documents through site-wide configuration.

In this case, processors MUST retrieve the file from the well-known URI /.well-known/csvm . (Well-known URIs are defined by [ RFC5785 ].) If no such file is located (i.e. the response results in a client error 4xx status code or a server error 5xx status code), processors MUST proceed as if this file were found with the content: following content which defines default locations:

 {+url}-metadata.json csv-metadata.json 

The response to retrieving /.well-known/csvm MAY be cached, subject to cache control directives. This includes caching an unsuccessful response such as a 404 Not Found .

This file MUST contain a URI template, as defined by [ URI-TEMPLATE ], on each line. Starting with the first such URI template, processors MUST :

  1. Expand the URI template, with the variable url being set to the URL of the requested delete: <a href="#dfn-tabular-data-file" class="internalDFN"> insert: <a href="#dfn-tabular-data-files" class="internalDFN" data-link-type="dfn"> tabular data file (with any fragment component of that URL removed).
  2. Resolve the resulting URL against the URL of the requested delete: <a href="#dfn-tabular-data-file" class="internalDFN"> insert: <a href="#dfn-tabular-data-files" class="internalDFN" data-link-type="dfn"> tabular data file .
  3. Attempt to retrieve a metadata document at that URL.
  4. If no metadata document is found at that location, or if the metadata file found at the location does not explicitly include a reference to the relevant delete: <a href="#dfn-tabular-data-file" class="internalDFN"> insert: <a href="#dfn-tabular-data-files" class="internalDFN" data-link-type="dfn"> tabular data file , perform these same steps on the next URI template, otherwise use that metadata document.

For example, if the delete: <a href="#dfn-tabular-data-file" class="internalDFN"> insert: <a href="#dfn-tabular-data-files" class="internalDFN" data-link-type="dfn"> tabular data file is at http://example.org/south-west/devon.csv then processors must attempt to locate a well-known file at http://example.org/.well-known/csvm . If that file contains:

Example 5
 {+url}.json csvm.json /csvm?file={url} 

the processor will first look for http://example.org/south-west/devon.csv.json . If there is no metadata file in that location, it will then look for http://example.org/south-west/csvm.json . Finally, if that also fails, it will look for http://example.org/csvm?file=http://example.org/south-west/devon.csv.json .

If no file were found at http://example.org/.well-known/csvm , the processor will use the default locations and try to retrieve metadata from http://example.org/south-west/devon.csv-metadata.json and, if unsuccessful, http://example.org/south-west/csv-metadata.json .

delete: <div class="issue atrisk" id="issue-555"> delete: <div class="issue-title" aria-level="4" role="heading" id="h-issue1"> delete: <span> Feature at Risk 555 delete: </span> delete: </div> delete: <p class="atrisk"> The use of a well-known location for defining URI patters used to locate metdata files is at risk. The Working Group solicits feedback on whether this mechanism is useful and whether it represents major implementation difficulties. delete: </p> delete: </div>

5.4 Embedded Metadata

Most syntaxes for tabular data provide a facility for delete: <dfn title="embedded metadata" id="dfn-embedded-metadata"> insert: <dfn data-dfn-type="dfn" id="dfn-embedding-metadata"> embedding metadata within the delete: <a href="#dfn-tabular-data-file" class="internalDFN"> insert: <a href="#dfn-tabular-data-files" class="internalDFN" data-link-type="dfn"> tabular data file itself. The definition of a syntax for tabular data SHOULD include a description of how the syntax maps to an annotated data model, and in particular how any embedded metadata is mapped into the vocabulary defined in [ tabular-metadata ]. Parsing based on the default dialect for CSV, as described in 8. Parsing Tabular Data , will extract delete: <a href="#dfn-column-titles" class="internalDFN"> insert: <a href="#dfn-column-titles" class="internalDFN" data-link-type="dfn"> column titles from the first row of a CSV file.

Example 6 : http://example.org/tree-ops.csv
 GID,On Street,Species,Trim Cycle,Inventory Date 1,ADDISON AV,Celtis australis,Large Tree Routine Prune,10/18/2010 2,EMERSON ST,Liquidambar styraciflua,Large Tree Routine Prune,6/2/2010 

The results of this can be found in section 8.2.1 Simple Example .

For another example, the following tab-delimited file contains embedded metadata where it is assumed that comments may be added using a # , and that the column types may be indicated using a #datatype annotation:

Example 7 : Tab-separated file containing embedded metadata
 # publisher City of Palo Alto # updated 12/31/2010 #name GID on_street species trim_cycle inventory_date #datatype string string string string date:M/D/YYYY GID On Street Species Trim Cycle Inventory Date 1 ADDISON AV Celtis australis Large Tree Routine Prune 10/18/2010 2 EMERSON ST Liquidambar styraciflua Large Tree Routine Prune 6/2/2010 

A processor that recognises this format may be able to extract and make sense of this embedded metadata.

6. Processing Tables

This section describes how particular types of applications should process tabular data and metadata files.

In many cases, an application will start processing from a metadata file. In that case, the initial metadata file is treated as overriding metadata and the application MUST NOT continue to retrieve other available metadata about each of the delete: <a href="#dfn-tabular-data-file" class="internalDFN"> insert: <a href="#dfn-tabular-data-files" class="internalDFN" data-link-type="dfn"> tabular data file s referenced by that initial metadata file other than delete: <a href="#dfn-embedded-metadata" class="internalDFN"> insert: <a href="#dfn-embedding-metadata" class="internalDFN" data-link-type="dfn"> embedded metadata .

In other cases, applications will start from a delete: <a href="#dfn-tabular-data-file" class="internalDFN"> insert: <a href="#dfn-tabular-data-files" class="internalDFN" data-link-type="dfn"> tabular data file , such as a CSV file, and locate metadata from that file. This metadata will be used to process the file as if the processor were starting from that metadata file.

For example, if a validator is passed a locally authored metadata file spending.json , which contains:

Example 8 : Metadata file referencing multiple tabular data files sharing a schema
  {     "tableSchema"   :     "government-spending.csv"   ,     "tables"   :     [{     "url"   :     "http://example.org/east-sussex-2015-03.csv"   ,     },     {     "url"   :     "http://example.org/east-sussex-2015-02.csv"     },     ...     ]     }  

the validator would validate all the listed tables, using the locally defined schema at government-spending.csv . It would also use the metadata embedded in the referenced CSV files; for example, when processing http://example.org/east-sussex-2015-03.csv , it would use delete: <a href="#dfn-embedded-metadata" class="internalDFN"> insert: <a href="#dfn-embedding-metadata" class="internalDFN" data-link-type="dfn"> embedded metadata within that file to verify that the CSV is delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#table-group-description-compatibility" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#table-group-description-compatibility" class="externalDFN"> compatible with the metadata.

If a validator is passed a delete: <a href="#dfn-tabular-data-file" class="internalDFN"> insert: <a href="#dfn-tabular-data-files" class="internalDFN" data-link-type="dfn"> tabular data file http://example.org/east-sussex-2015-03.csv , the validator would use the metadata located from the CSV file: the first metadata file found through the Link headers found when retrieving that file, or located through a site-wide location configuration.

delete: <div class="note-title" aria-level="3" role="heading" id="h-note9"> insert: <div class="note-title" aria-level="3" role="heading" id="h-note12">
Note

Starting with a metadata file can remove the need to perform additional requests to locate linked metadata, or metadata retrieved through site-wide location configuration

6.1 Creating Annotated Tables

After locating metadata, metadata is delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dfn-normalization" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dfn-normalized" class="externalDFN"> normalized and coerced into a single delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dfn-table-group-description" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dfn-table-group-description" class="externalDFN"> table group description . When starting with a metadata file, this involves normalizing the provided metadata file and verifying that the delete: <a href="#dfn-embedded-metadata" class="internalDFN"> insert: <a href="#dfn-embedding-metadata" class="internalDFN" data-link-type="dfn"> embedded metadata for each delete: <a href="#dfn-tabular-data-file" class="internalDFN"> insert: <a href="#dfn-tabular-data-files" class="internalDFN" data-link-type="dfn"> tabular data file referenced from the metadata is delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#table-group-description-compatibility" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#table-group-description-compatibility" class="externalDFN"> compatible with the metadata. When starting with a delete: <a href="#dfn-tabular-data-file" class="internalDFN"> insert: <a href="#dfn-tabular-data-files" class="internalDFN" data-link-type="dfn"> tabular data file , this involves locating the first metadata file as described in section 5. Locating Metadata and normalizing into a single descriptor.

If processing starts with a delete: <a href="#dfn-tabular-data-file" class="internalDFN"> insert: <a href="#dfn-tabular-data-files" class="internalDFN" data-link-type="dfn"> tabular data file , implementations:

  1. Retrieve the tabular data file.
  2. Retrieve the first metadata file ( FM ) as described in section 5. Locating Metadata :
    1. metadata supplied by the user (see section 5.1 Overriding Metadata ).
    2. metadata referenced from a Link Header that may be returned when retrieving the tabular data file (see section 5.2 Link Header ).
    3. metadata retrieved through a site-wide location configuration (see delete: <a href="#site-wide-location-configuration" class="sectionRef sec-ref"> insert: <a href="#default-locations-and-site-wide-location-configuration" class="sectionRef sec-ref"> section 5.3 Default Locations and Site-wide Location Configuration ).
    4. delete: <a href="#dfn-embedded-metadata" class="internalDFN"> insert: <a href="#dfn-embedding-metadata" class="internalDFN" data-link-type="dfn"> embedded metadata as defined in section 5.4 Embedded Metadata with a single tables entry where the url property is set from that of the delete: <a href="#dfn-tabular-data-file" class="internalDFN"> insert: <a href="#dfn-tabular-data-files" class="internalDFN" data-link-type="dfn"> tabular data file .
  3. Proceed as if the process starts with FM .

If the process starts with a metadata file:

  1. Retrieve the metadata file yielding the metadata UM (which is treated as overriding metadata, see section 5.1 Overriding Metadata ).
  2. Normalize UM using the process defined in delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#normalization"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#normalization"> Normalization in [ tabular-metadata ], coercing UM into a delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dfn-table-group-description" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dfn-table-group-description" class="externalDFN"> table group description , if necessary.
  3. For each delete: <a href="#dfn-table" class="internalDFN"> insert: <a href="#dfn-table" class="internalDFN" data-link-type="dfn"> table ( TM ) in UM in order, create one or more delete: <a title="annotated table" href="#dfn-annotated-table" class="internalDFN"> insert: <a href="#dfn-annotated-table" class="internalDFN" data-link-type="dfn"> annotated tables :
    1. Extract the delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dialect-descriptions"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dialect-descriptions"> dialect description ( DD ) from UM for the delete: <a href="#dfn-table" class="internalDFN"> insert: <a href="#dfn-table" class="internalDFN" data-link-type="dfn"> table associated with the tabular data file. If there is no such dialect description, extract the first available dialect description from a delete: <a href="#dfn-group-of-tables" class="internalDFN"> insert: <a href="#dfn-group-of-tables" class="internalDFN" data-link-type="dfn"> group of tables in which the tabular data file is described. Otherwise use the default dialect description.
    2. If using the default delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dialect-descriptions"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dialect-descriptions"> dialect description , override default values in DD based on HTTP headers found when retrieving the tabular data file:
      • If the media type from the Content-Type header is text/tsv text/tab-separated-values , set delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dialect-delimiter" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dialect-delimiter" class="externalDFN"> delimiter to TAB in DD .
      • If the Content-Type header includes the header parameter with a value of absent , set delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dialect-header" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dialect-header" class="externalDFN"> header to false in DD .
      • If the Content-Type header includes the charset parameter, set delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dialect-encoding" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dialect-encoding" class="externalDFN"> encoding to this value in DD .
    3. Parse the tabular data file, using DD as a guide, to create a basic tabular data model ( T ) and extract delete: <a href="#dfn-embedded-metadata" class="internalDFN"> insert: <a href="#dfn-embedding-metadata" class="internalDFN" data-link-type="dfn"> embedded metadata ( EM ), for example from the delete: <a href="#dfn-header-line" class="internalDFN"> insert: <a href="#dfn-header-line" class="internalDFN" data-link-type="dfn"> header line .

      delete: <div class="note-title" aria-level="4" role="heading" id="h-note10"> insert: <div class="note-title" aria-level="4" role="heading" id="h-note13">
      Note

      This specification provides a non-normative definition for parsing CSV-based files, including the extraction of delete: <a href="#dfn-embedded-metadata" class="internalDFN"> insert: <a href="#dfn-embedding-metadata" class="internalDFN" data-link-type="dfn"> embedded metadata , in section 8. Parsing Tabular Data . This specification does not define any syntax for embedded metadata beyond this; whatever syntax is used, it's assumed that metadata can be mapped to the vocabulary defined in [ tabular-metadata ].

    4. If a Content-Language HTTP header was found when retrieving the tabular data file, and the value provides a single language, set the delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#cell-language" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#cell-language" class="externalDFN"> lang inherited property to this value in TM , unless TM already has a delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#cell-language" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#cell-language" class="externalDFN"> lang inherited property.
    5. Verify that TM is compatible with EM using the procedure defined in delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#table-description-compatibility"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#table-description-compatibility"> Table Description Compatibility in [ tabular-metadata ]; if TM is not compatible with EM validators MUST raise an error, other processors MUST generate a warning and continue processing.
    6. Use the metadata TM to add annotations to the tabular data model T as described in delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#annotating-tables"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#annotating-tables"> Section 2 Annotating Tables in [ tabular-metadata ].

6.2 Metadata Compatibility

When processing a delete: <a href="#dfn-tabular-data-file" class="internalDFN"> insert: <a href="#dfn-tabular-data-files" class="internalDFN" data-link-type="dfn"> tabular data file using metadata as discovered using section 5. Locating Metadata , processors MUST ensure that the metadata and delete: <a href="#dfn-tabular-data-file" class="internalDFN"> insert: <a href="#dfn-tabular-data-files" class="internalDFN" data-link-type="dfn"> tabular data file are compatible, this is typically done by extracting delete: <a href="#dfn-embedded-metadata" class="internalDFN"> insert: <a href="#dfn-embedding-metadata" class="internalDFN" data-link-type="dfn"> embedded metadata from the delete: <a href="#dfn-tabular-data-file" class="internalDFN"> insert: <a href="#dfn-tabular-data-files" class="internalDFN" data-link-type="dfn"> tabular data file and determining that the provided or discovered metadata is compatible with the delete: <a href="#dfn-embedded-metadata" class="internalDFN"> insert: <a href="#dfn-embedding-metadata" class="internalDFN" data-link-type="dfn"> embedded metadata using the procedure defined in delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#table-description-compatibility"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#table-description-compatibility"> Table Compatibility in [ tabular-metadata ].

6.3 URL Normalization

Metadata Discovery and Compatibility involve comparing URLs. When comparing URLs, processors MUST use Syntax-Based Normalization as defined in [ RFC3968 ]. Processors MUST perform Scheme-Based Normalization for HTTP ( 80 ) and HTTPS ( 443 ) and SHOULD perform Scheme-Based Normalization for other well-known schems. schemes.

6.4 Parsing Cells

Unlike many other data formats, tabular data is designed to be read by humans. For that reason, it's common for data to be represented within tabular data in a human-readable way. The delete: <a title="column datatype" href="#dfn-column-datatype" class="internalDFN"> insert: <a data-lt="column datatype" href="#dfn-datatype" class="internalDFN" data-link-type="dfn"> datatype , delete: <a title="column default" href="#dfn-column-default" class="internalDFN"> insert: <a data-lt="column default" href="#dfn-default" class="internalDFN" data-link-type="dfn"> default , delete: <a title="column lang" href="#dfn-column-lang" class="internalDFN"> insert: <a data-lt="column lang" href="#dfn-lang" class="internalDFN" data-link-type="dfn"> lang , delete: <a title="column null" href="#dfn-column-null" class="internalDFN"> insert: <a data-lt="column null" href="#dfn-null" class="internalDFN" data-link-type="dfn"> null , delete: <a title="column required" href="#dfn-column-required" class="internalDFN"> insert: <a data-lt="column required" href="#dfn-required" class="internalDFN" data-link-type="dfn"> required , and delete: <a title="column separator" href="#dfn-column-separator" class="internalDFN"> insert: <a data-lt="column separator" href="#dfn-separator" class="internalDFN" data-link-type="dfn"> separator annotations provide the information needed to parse the delete: <a title="cell string value" href="#dfn-cell-string-value" class="internalDFN"> insert: <a data-lt="cell string value" href="#dfn-string-value" class="internalDFN" data-link-type="dfn"> string value of a cell into its (semantic) delete: <a title="cell value" href="#dfn-cell-value" class="internalDFN"> insert: <a data-lt="cell value" href="#dfn-value" class="internalDFN" data-link-type="dfn"> value annotation. This is used:

The process of parsing a cell creates a delete: <a href="#dfn-cell" class="internalDFN"> insert: <a href="#dfn-cell" class="internalDFN" data-link-type="dfn"> cell with annotations based on the original string value, parsed value and other delete: <a href="#dfn-column" class="internalDFN"> insert: <a href="#dfn-column" class="internalDFN" data-link-type="dfn"> column annotations and adds the cell to the list of delete: <a title="row cells" href="#dfn-row-cells" class="internalDFN"> insert: <a data-lt="row cells" href="#dfn-cell" class="internalDFN" data-link-type="dfn"> cells in a delete: <a href="#dfn-row" class="internalDFN"> insert: <a href="#dfn-row" class="internalDFN" data-link-type="dfn"> row and delete: <a title="column cells" href="#dfn-column-cells" class="internalDFN"> insert: <a data-lt="column cells" href="#dfn-cell" class="internalDFN" data-link-type="dfn"> cells in a delete: <a href="#dfn-column" class="internalDFN"> insert: <a href="#dfn-column" class="internalDFN" data-link-type="dfn"> column :

After parsing, the delete: <a href="#dfn-cell-value" class="internalDFN"> insert: <a href="#dfn-value" class="internalDFN" data-link-type="dfn"> cell value can be:

The process of parsing the string value into a single value or a list of values is as follows:

  1. unless the delete: <a href="#dfn-datatype-base" class="internalDFN"> insert: <a href="#dfn-base" class="internalDFN" data-link-type="dfn"> datatype base is string , json , xml , html or anyAtomicType , replace all carriage return ( #xD ), line feed ( #xA ), and tab ( #x9 ) characters with space characters.
  2. unless the delete: <a href="#dfn-datatype-base" class="internalDFN"> insert: <a href="#dfn-base" class="internalDFN" data-link-type="dfn"> datatype base is string , json , xml , html , anyAtomicType , or normalizedString , strip leading and trailing whitespace from the delete: <a title="cell string value" href="#dfn-cell-string-value" class="internalDFN"> insert: <a data-lt="cell string value" href="#dfn-string-value" class="internalDFN" data-link-type="dfn"> string value and replace all instances of two or more whitespace characters with a single space character.
  3. if the normalized string is an empty string, apply the remaining steps to the string given by the delete: <a href="#dfn-column-default" class="internalDFN"> insert: <a href="#dfn-default" class="internalDFN" data-link-type="dfn"> column default annotation.
  4. if the delete: <a href="#dfn-column-separator" class="internalDFN"> insert: <a href="#dfn-separator" class="internalDFN" data-link-type="dfn"> column separator annotation is not null and the normalized string is an empty string, the delete: <a href="#dfn-cell-value" class="internalDFN"> insert: <a href="#dfn-value" class="internalDFN" data-link-type="dfn"> cell value is an empty list. If the delete: <a href="#dfn-column-required" class="internalDFN"> insert: <a href="#dfn-required" class="internalDFN" data-link-type="dfn"> column required annotation is true , add an error to the list of delete: <a title="cell errors" href="#dfn-cell-errors" class="internalDFN"> insert: <a data-lt="cell errors" href="#dfn-errors" class="internalDFN" data-link-type="dfn"> errors for the cell.
  5. if the delete: <a href="#dfn-column-separator" class="internalDFN"> insert: <a href="#dfn-separator" class="internalDFN" data-link-type="dfn"> column separator annotation is not null , the delete: <a href="#dfn-cell-value" class="internalDFN"> insert: <a href="#dfn-value" class="internalDFN" data-link-type="dfn"> cell value is a list of values; set the delete: <a title="cell value list" href="#dfn-cell-value-list" class="internalDFN"> insert: <a data-lt="cell value list" href="#dfn-list" class="internalDFN" data-link-type="dfn"> list annotation on the delete: <a href="#dfn-cell" class="internalDFN"> insert: <a href="#dfn-cell" class="internalDFN" data-link-type="dfn"> cell to true , and create the delete: <a href="#dfn-cell-value" class="internalDFN"> insert: <a href="#dfn-value" class="internalDFN" data-link-type="dfn"> cell value created by:
    1. if the normalized string is the same as any one of the values of the delete: <a href="#dfn-column-null" class="internalDFN"> insert: <a href="#dfn-null" class="internalDFN" data-link-type="dfn"> column null annotation, then the resulting value is null .
    2. split the normalized string at the character specified by the delete: <a href="#dfn-column-separator" class="internalDFN"> insert: <a href="#dfn-separator" class="internalDFN" data-link-type="dfn"> column separator annotation.
    3. unless the delete: <a href="#dfn-datatype-base" class="internalDFN"> insert: <a href="#dfn-base" class="internalDFN" data-link-type="dfn"> datatype base is string or anyAtomicType , strip leading and trailing whitespace from these strings.
    4. applying the remaining steps to each of the strings in turn.
  6. if the string is an empty string, apply the remaining steps to the string given by the delete: <a href="#dfn-column-default" class="internalDFN"> insert: <a href="#dfn-default" class="internalDFN" data-link-type="dfn"> column default annotation.
  7. if the string is the same as any one of the values of the delete: <a href="#dfn-column-null" class="internalDFN"> insert: <a href="#dfn-null" class="internalDFN" data-link-type="dfn"> column null annotation, then the resulting value is null . If the delete: <a href="#dfn-column-separator" class="internalDFN"> insert: <a href="#dfn-separator" class="internalDFN" data-link-type="dfn"> column separator annotation is null and the delete: <a href="#dfn-column-required" class="internalDFN"> insert: <a href="#dfn-required" class="internalDFN" data-link-type="dfn"> column required annotation is true , add an error to the list of delete: <a title="cell errors" href="#dfn-cell-errors" class="internalDFN"> insert: <a data-lt="cell errors" href="#dfn-errors" class="internalDFN" data-link-type="dfn"> errors for the cell.
  8. parse the string using the delete: <a href="#dfn-datatype-format" class="internalDFN"> insert: <a href="#dfn-format" class="internalDFN" data-link-type="dfn"> datatype format if one is specified, as described below to give a value with an associated delete: <a title="cell value datatype" href="#dfn-cell-value-datatype" class="internalDFN"> insert: <a data-lt="cell value datatype" href="#dfn-datatype" class="internalDFN" data-link-type="dfn"> datatype . If the delete: <a href="#dfn-datatype-base" class="internalDFN"> insert: <a href="#dfn-base" class="internalDFN" data-link-type="dfn"> datatype base is string , or there is no datatype , the value has an associated delete: <a title="cell value language" href="#dfn-cell-value-language" class="internalDFN"> insert: <a data-lt="cell value language" href="#dfn-language" class="internalDFN" data-link-type="dfn"> language from the delete: <a href="#dfn-column-lang" class="internalDFN"> insert: <a href="#dfn-lang" class="internalDFN" data-link-type="dfn"> column lang annotation. If there are any errors, add them to the list of delete: <a title="cell errors" href="#dfn-cell-errors" class="internalDFN"> insert: <a data-lt="cell errors" href="#dfn-errors" class="internalDFN" data-link-type="dfn"> errors for the cell; in this case the value has a delete: <a title="cell value datatype" href="#dfn-cell-value-datatype" class="internalDFN"> insert: <a data-lt="cell value datatype" href="#dfn-datatype" class="internalDFN" data-link-type="dfn"> datatype of string ; if the delete: <a href="#dfn-datatype-base" class="internalDFN"> insert: <a href="#dfn-base" class="internalDFN" data-link-type="dfn"> datatype base is string , or there is no datatype , the value has an associated delete: <a title="cell value language" href="#dfn-cell-value-language" class="internalDFN"> insert: <a data-lt="cell value language" href="#dfn-language" class="internalDFN" data-link-type="dfn"> language from the delete: <a href="#dfn-column-lang" class="internalDFN"> insert: <a href="#dfn-lang" class="internalDFN" data-link-type="dfn"> column lang annotation.
  9. validate the value based on the length constraints described in section 4.6.1 Length Constraints , the value constraints described in section 4.6.2 Value Constraints and the delete: <a href="#dfn-datatype-format" class="internalDFN"> insert: <a href="#dfn-format" class="internalDFN" data-link-type="dfn"> datatype format annotation if one is specified, as described below. If there are any errors, add them to the list of delete: <a title="cell errors" href="#dfn-cell-errors" class="internalDFN"> insert: <a data-lt="cell errors" href="#dfn-errors" class="internalDFN" data-link-type="dfn"> errors for the cell.

The final value (or values) become the delete: <a title="cell value" href="#dfn-cell-value" class="internalDFN"> insert: <a data-lt="cell value" href="#dfn-value" class="internalDFN" data-link-type="dfn"> value annotation on the delete: <a href="#dfn-cell" class="internalDFN"> insert: <a href="#dfn-cell" class="internalDFN" data-link-type="dfn"> cell .

If there is a delete: <a title="column about URL" href="#dfn-column-about-url" class="internalDFN"> insert: <a data-lt="column about URL" href="#dfn-column-about-url" class="internalDFN" data-link-type="dfn"> about URL annotation on the delete: <a href="#dfn-column" class="internalDFN"> insert: <a href="#dfn-column" class="internalDFN" data-link-type="dfn"> column , it becomes the delete: <a title="cell about URL" href="#dfn-cell-about-url" class="internalDFN"> insert: <a data-lt="cell about URL" href="#dfn-cell-about-url" class="internalDFN" data-link-type="dfn"> about URL annotation on the delete: <a href="#dfn-cell" class="internalDFN"> insert: <a href="#dfn-cell" class="internalDFN" data-link-type="dfn"> cell , after being transformed into an absolute URL as described in delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#uri-template-properties"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#uri-template-properties"> URI Template Properties of [ tabular-metadata ].

If there is a delete: <a title="column property URL" href="#dfn-column-property-url" class="internalDFN"> insert: <a data-lt="column property URL" href="#dfn-column-property-url" class="internalDFN" data-link-type="dfn"> property URL annotation on the delete: <a href="#dfn-column" class="internalDFN"> insert: <a href="#dfn-column" class="internalDFN" data-link-type="dfn"> column , it becomes the delete: <a title="cell property URL" href="#dfn-cell-property-url" class="internalDFN"> insert: <a data-lt="cell property URL" href="#dfn-cell-property-url" class="internalDFN" data-link-type="dfn"> property URL annotation on the delete: <a href="#dfn-cell" class="internalDFN"> insert: <a href="#dfn-cell" class="internalDFN" data-link-type="dfn"> cell , after being transformed into an absolute URL as described in delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#uri-template-properties"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#uri-template-properties"> URI Template Properties of [ tabular-metadata ].

If there is a delete: <a title="column value URL" href="#dfn-column-value-url" class="internalDFN"> insert: <a data-lt="column value URL" href="#dfn-column-value-url" class="internalDFN" data-link-type="dfn"> value URL annotation on the delete: <a href="#dfn-column" class="internalDFN"> insert: <a href="#dfn-column" class="internalDFN" data-link-type="dfn"> column , it becomes the delete: <a title="cell value URL" href="#dfn-cell-value-url" class="internalDFN"> insert: <a data-lt="cell value URL" href="#dfn-cell-value-url" class="internalDFN" data-link-type="dfn"> value URL annotation on the delete: <a href="#dfn-cell" class="internalDFN"> insert: <a href="#dfn-cell" class="internalDFN" data-link-type="dfn"> cell , after being transformed into an absolute URL as described in delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#uri-template-properties"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#uri-template-properties"> URI Template Properties of [ tabular-metadata ]. The delete: <a title="column value URL" href="#dfn-column-value-url" class="internalDFN"> insert: <a data-lt="column value URL" href="#dfn-column-value-url" class="internalDFN" data-link-type="dfn"> value URL annotation is null if the delete: <a href="#dfn-cell-value" class="internalDFN"> insert: <a href="#dfn-value" class="internalDFN" data-link-type="dfn"> cell value is null and the delete: <a href="#dfn-column-virtual" class="internalDFN"> insert: <a href="#dfn-virtual" class="internalDFN" data-link-type="dfn"> column virtual annotation is false .

6.4.1 Parsing examples

This section is non-normative.

When delete: <a href="#dfn-datatype" class="internalDFN"> insert: <a href="#dfn-datatype" class="internalDFN" data-link-type="dfn"> datatype annotation is available, the delete: <a title="cell value" href="#dfn-cell-value" class="internalDFN"> insert: <a data-lt="cell value" href="#dfn-value" class="internalDFN" data-link-type="dfn"> value of a cell is the same as its delete: <a title="cell string value" href="#dfn-cell-string-value" class="internalDFN"> insert: <a data-lt="cell string value" href="#dfn-string-value" class="internalDFN" data-link-type="dfn"> string value . For example, a cell with a string value of "99" would similarly have the (semantic) value "99" .

If a delete: <a href="#dfn-datatype-base" class="internalDFN"> insert: <a href="#dfn-base" class="internalDFN" data-link-type="dfn"> datatype base is provided for the cell, that is used to create a (semantic) delete: <a title="cell value" href="#dfn-cell-value" class="internalDFN"> insert: <a data-lt="cell value" href="#dfn-value" class="internalDFN" data-link-type="dfn"> value for the cell. For example, if the metadata contains:

Example 9
  "datatype"   :     "integer"  

for the cell with the string value "99" then the value of that cell will be the integer 99 . A cell whose string value was not a valid integer (such as "one" or "1.0" ) would be assigned that string value as its (semantic) value annotation, but also have a validation error listed in its delete: <a title="cell errors" href="#dfn-cell-errors" class="internalDFN"> insert: <a data-lt="cell errors" href="#dfn-errors" class="internalDFN" data-link-type="dfn"> errors annotation.

Sometimes data uses special codes to indicate unknown or null values. For example, a particular column might contain a number that is expected to be between 1 and 10 , with the string 99 used in the original tabular data file to indicate a null value. The metadata for such a column would include:

Example 10
  "datatype"   :     {     "base"   :     "integer"   ,     "minimum"   :     1   ,     "maximum"   :     10     },     "null"   :     "99"  

In this case, a cell with a string value of "5" would have the (semantic) value of the integer 5 ; a cell with a string value of "99" would have the value null .

Similarly, a cell may be assigned a default value if the string value for the cell is empty. A configuration such as:

Example 11
  "datatype"   :     {     "base"   :     "integer"   ,     "minimum"   :     1   ,     "maximum"   :     10     },     "default"   :     "5"  

In this case, a cell whose string value is "" would be assigned the value of the integer 5 . A cell whose string value contains whitespace, such as a single tab character, would also be assigned the value of the integer 5 : when the datatype is something other than string or anyAtomicType , leading and trailing whitespace is stripped from string values before the remainder of the processing is carried out.

Cells can contain sequences of values. For example, a cell might have the string value "1 5 7.0" . In this case, the separator is a space character. The appropriate configuration would be:

Example 12
  "datatype"   :     {     "base"   :     "integer"   ,     "minimum"   :     1   ,     "maximum"   :     10     },     "default"   :     "5"   ,     "separator"   :     " "  

and this would mean that the cell's value would be an array containing two integers and a string: [1, 5, "7.0"] . The final value of the array is a string because it is not a valid integer; the cell's delete: <a title="cell errors" href="#dfn-cell-errors" class="internalDFN"> insert: <a data-lt="cell errors" href="#dfn-errors" class="internalDFN" data-link-type="dfn"> errors annotation will also contain a validation error.

Also, with this configuration, if the string value of the cell were "" (i.e. it was an empty cell) the value of the cell would be an empty list.

A delete: <a href="#dfn-cell-value" class="internalDFN"> insert: <a href="#dfn-value" class="internalDFN" data-link-type="dfn"> cell value can be inserted into a URL created using a delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dfn-uri-template-property" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dfn-uri-template-properties" class="externalDFN"> URI template property such as valueUrl . For example, if a cell with the delete: <a title="cell string value" href="#dfn-cell-string-value" class="internalDFN"> insert: <a data-lt="cell string value" href="#dfn-string-value" class="internalDFN" data-link-type="dfn"> string value "1 5 7.0" were in a column named values , defined with:

Example 13
  "datatype"   :     "decimal"   ,     "separator"   :     " "   ,     "valueUrl"   :     "{?values}"  

then after expansion of the URI template, the resulting valueUrl would be ?values=1.0,5.0,7.0 . The canonical representations of the decimal values are used within the URL.

6.4.2 Formats for numeric types

By default, numeric values must be in the formats defined in [ xmlschema11-2 ]. It is not uncommon for numbers within tabular data to be formatted for human consumption, which may involve using commas for decimal points, grouping digits in the number using commas, or adding percent signs to the number.

If the delete: <a href="#dfn-datatype-base" class="internalDFN"> insert: <a href="#dfn-base" class="internalDFN" data-link-type="dfn"> datatype base is a numeric type, the delete: <a href="#dfn-datatype-format" class="internalDFN"> insert: <a href="#dfn-format" class="internalDFN" data-link-type="dfn"> datatype format annotation indicates the expected format for that number. Its value MUST be either a single string or an object with one or more of the properties:

delete: <dfn title="datatype format decimalChar" id="dfn-datatype-format-decimalchar"> insert: <dfn data-dfn-type="dfn" id="dfn-decimalchar"> decimalChar
A string whose value is used to represent a decimal point within the number. The default value is "." . If the supplied value is not a string, implementations MUST issue a warning and proceed as if the property had not been specified.
delete: <dfn title="datatype format groupChar" id="dfn-datatype-format-groupchar"> insert: <dfn data-dfn-type="dfn" id="dfn-groupchar"> groupChar
A string whose value is used to group digits within the number. The default value is null . If the supplied value is not a string, implementations MUST issue a warning and proceed as if the property had not been specified.
delete: <dfn title="datatype format pattern" id="dfn-datatype-format-pattern"> insert: <dfn data-dfn-type="dfn" id="dfn-pattern"> pattern
A number format pattern as defined in [ UAX35 ]. Implementations MUST recognise number format patterns containing the symbols 0 , # , the specified delete: <a title="datatype format decimalChar" href="#dfn-datatype-format-decimalchar" class="internalDFN"> insert: <a data-lt="datatype format decimalChar" href="#dfn-decimalchar" class="internalDFN" data-link-type="dfn"> decimalChar (or "." if unspecified), the specified delete: <a title="datatype format groupChar" href="#dfn-datatype-format-groupchar" class="internalDFN"> insert: <a data-lt="datatype format groupChar" href="#dfn-groupchar" class="internalDFN" data-link-type="dfn"> groupChar (or "," if unspecified), E , + , % and . Implementations MAY additionally recognise number format patterns containing other special pattern characters defined in [ UAX35 ]. If the supplied value is not a string, or if it contains an invalid number format pattern or uses special pattern characters that the implementation does not recognise, implementations MUST issue a warning and proceed as if the property had not been specified.

If the delete: <a href="#dfn-datatype-format" class="internalDFN"> insert: <a href="#dfn-format" class="internalDFN" data-link-type="dfn"> datatype format annotation is a single string, this is interpreted in the same way as if it were an object with a delete: <a title="datatype format pattern" href="#dfn-datatype-format-pattern" class="internalDFN"> insert: <a data-lt="datatype format pattern" href="#dfn-pattern" class="internalDFN" data-link-type="dfn"> pattern property whose value is that string.

If the delete: <a title="datatype format groupChar" href="#dfn-datatype-format-groupchar" class="internalDFN"> insert: <a data-lt="datatype format groupChar" href="#dfn-groupchar" class="internalDFN" data-link-type="dfn"> groupChar is specified, but no delete: <a title="datatype format pattern" href="#dfn-datatype-format-pattern" class="internalDFN"> insert: <a data-lt="datatype format pattern" href="#dfn-pattern" class="internalDFN" data-link-type="dfn"> pattern is supplied, when parsing the delete: <a title="cell string value" href="#dfn-cell-string-value" class="internalDFN"> insert: <a data-lt="cell string value" href="#dfn-string-value" class="internalDFN" data-link-type="dfn"> string value of a cell against this format specification, implementations MUST recognise and parse numbers that consist of:

  1. an optional + or - sign,
  2. followed by a decimal digit ( 0-9 ),
  3. followed by any number of decimal digits ( 0-9 ) and the string specified as the delete: <a title="datatype format groupChar" href="#dfn-datatype-format-groupchar" class="internalDFN"> insert: <a data-lt="datatype format groupChar" href="#dfn-groupchar" class="internalDFN" data-link-type="dfn"> groupChar ,
  4. followed by an optional delete: <a title="datatype format decimalChar" href="#dfn-datatype-format-decimalchar" class="internalDFN"> insert: <a data-lt="datatype format decimalChar" href="#dfn-decimalchar" class="internalDFN" data-link-type="dfn"> decimalChar followed by one or more decimal digits ( 0-9 ),
  5. followed by an optional exponent, consisting of an E followed by an optional + or - sign followed by one or more decimal digits ( 0-9 ), or
  6. followed by an optional percent ( % ) or per-mille ( ) sign.

or that are one of the special values:

  1. NaN ,
  2. INF , or
  3. -INF .

Implementations MAY also recognise numeric values that are in any of the standard-decimal, standard-percent or standard-scientific formats listed in the Unicode Common Locale Data Repository .

Implementations MUST add a validation error to the delete: <a title="cell errors" href="#dfn-cell-errors" class="internalDFN"> insert: <a data-lt="cell errors" href="#dfn-errors" class="internalDFN" data-link-type="dfn"> errors annotation for the delete: <a href="#dfn-cell" class="internalDFN"> insert: <a href="#dfn-cell" class="internalDFN" data-link-type="dfn"> cell , and set the cell delete: <a title="cell value" href="#dfn-cell-value" class="internalDFN"> insert: <a data-lt="cell value" href="#dfn-value" class="internalDFN" data-link-type="dfn"> value to a string rather than a number if the string being parsed:

  • is not in the format specified in the delete: <a title="datatype format pattern" href="#dfn-datatype-format-pattern" class="internalDFN"> insert: <a data-lt="datatype format pattern" href="#dfn-pattern" class="internalDFN" data-link-type="dfn"> pattern , if one is defined
  • otherwise, if the string
    • does not meet the numeric format defined above,
    • contains two consecutive delete: <a title="datatype format groupChar" href="#dfn-datatype-format-groupchar" class="internalDFN"> insert: <a data-lt="datatype format groupChar" href="#dfn-groupchar" class="internalDFN" data-link-type="dfn"> groupChar strings,
  • contains the delete: <a title="datatype format decimalChar" href="#dfn-datatype-format-decimalchar" class="internalDFN"> insert: <a data-lt="datatype format decimalChar" href="#dfn-decimalchar" class="internalDFN" data-link-type="dfn"> decimalChar , if the delete: <a href="#dfn-datatype-base" class="internalDFN"> insert: <a href="#dfn-base" class="internalDFN" data-link-type="dfn"> datatype base is integer or one of its sub-types,
  • contains an exponent, if the delete: <a href="#dfn-datatype-base" class="internalDFN"> insert: <a href="#dfn-base" class="internalDFN" data-link-type="dfn"> datatype base is decimal or one of its sub-types, or
  • is one of the special values NaN , INF , or -INF , if the delete: <a href="#dfn-datatype-base" class="internalDFN"> insert: <a href="#dfn-base" class="internalDFN" data-link-type="dfn"> datatype base is decimal or one of its sub-types.

Implementations MUST use the sign, exponent, percent, and per-mille signs when parsing the delete: <a title="cell string value" href="#dfn-cell-string-value" class="internalDFN"> insert: <a data-lt="cell string value" href="#dfn-string-value" class="internalDFN" data-link-type="dfn"> string value of a cell to provide the delete: <a title="cell value" href="#dfn-cell-value" class="internalDFN"> insert: <a data-lt="cell value" href="#dfn-value" class="internalDFN" data-link-type="dfn"> value of the cell. For example, the string value "-25%" must be interpreted as -0.25 and the string value "1E6" as 1000000 .

6.4.3 Formats for booleans

Boolean values may be represented in many ways aside from the standard 1 and 0 or true and false .

If the delete: <a href="#dfn-datatype-base" class="internalDFN"> insert: <a href="#dfn-base" class="internalDFN" data-link-type="dfn"> datatype base for a cell is boolean , the delete: <a href="#dfn-datatype-format" class="internalDFN"> insert: <a href="#dfn-format" class="internalDFN" data-link-type="dfn"> datatype format annotation provides the true value followed by the false value, separated by | . For example if format is Y|N then cells must hold either Y or N with Y meaning true and N meaning false . If the format does not follow this syntax, implementations MUST issue a warning and proceed as if no format had been provided.

The resulting delete: <a href="#dfn-cell-value" class="internalDFN"> insert: <a href="#dfn-value" class="internalDFN" data-link-type="dfn"> cell value will be one or more boolean true or false values.

6.4.4 Formats for dates and times

By default, dates and times are assumed to be in the format defined in [ xmlschema11-2 ]. However dates and times are commonly represented in tabular data in other formats.

If the delete: <a href="#dfn-datatype-base" class="internalDFN"> insert: <a href="#dfn-base" class="internalDFN" data-link-type="dfn"> datatype base is a date or time type, the delete: <a href="#dfn-datatype-format" class="internalDFN"> insert: <a href="#dfn-format" class="internalDFN" data-link-type="dfn"> datatype format annotation indicates the expected format for that date or time.

The supported date and time format patterns listed here are expressed in terms of the date field symbols defined in [ UAX35 ]. These formats MUST be recognised by implementations and MUST be interpreted as defined in that specification. Implementations MAY additionally recognise other date format patterns . Implementations MUST issue a warning if the date format pattern is invalid or not recognised and proceed as if no date format pattern had been provided.

delete: <div class="note-title" aria-level="5" role="heading" id="h-note11"> insert: <div class="note-title" aria-level="5" role="heading" id="h-note14">
Note

For interoperability, authors of metadata documents SHOULD use only the formats listed in this section.

The following date format patterns MUST be recognized by implementations:

  • yyyy-MM-dd e.g., 2015-03-22
  • yyyyMMdd e.g., 20150322
  • dd-MM-yyyy e.g., 22-03-2015
  • d-M-yyyy e.g., 22-3-2015
  • MM-dd-yyyy e.g., 03-22-2015
  • M-d-yyyy e.g., 3-22-2015
  • dd/MM/yyyy e.g., 22/03/2015
  • d/M/yyyy e.g., 22/3/2015
  • MM/dd/yyyy e.g., 03/22/2015
  • M/d/yyyy e.g., 3/22/2015
  • dd.MM.yyyy e.g., 22.03.2015
  • d.M.yyyy e.g., 22.3.2015
  • MM.dd.yyyy e.g., 03.22.2015
  • M.d.yyyy e.g., 3.22.2015

The following time format patterns MUST be recognized by implementations:

  • HH:mm:ss.S with one or more trailing S characters indicating the maximum number of fractional seconds e.g., HH:mm:ss.SSS for 15:02:37.143
  • HH:mm:ss e.g., 15:02:37
  • HHmmss e.g., 150237
  • HH:mm e.g., 15:02
  • HHmm e.g., 1502

The following date/time format patterns MUST be recognized by implementations:

  • yyyy-MM-ddTHH:mm:ss.S with one or more trailing S characters indicating the maximum number of fractional seconds e.g., yyyy-MM-ddTHH:mm:ss.SSS for 2015-03-15T15:02:37.143
  • yyyy-MM-ddTHH:mm:ss e.g., 2015-03-15T15:02:37
  • yyyy-MM-ddTHH:mm e.g., 2015-03-15T15:02
  • any of the date formats above, followed by a single space, followed by any of the time formats above, e.g., M/d/yyyy HH:mm for 3/22/2015 15:02 or dd.MM.yyyy HH:mm:ss for 22.03.2015 15:02:37

Implementations MUST also recognise date, time, and date/time format patterns that end with timezone markers consisting of between one and three x or X characters, possibly after a single space. These MUST be interpreted as follows:

  • X e.g., -08 , +0530 , or Z (minutes are optional)
  • XX e.g., -0800 , +0530 , or Z
  • XXX e.g., -08:00 , +05:30 , or Z
  • x e.g., -08 or +0530 ( Z is not permitted)
  • xx e.g., -0800 or +0530 ( Z is not permitted)
  • xxx e.g., -08:00 or +05:30 ( Z is not permitted)

For example, date format patterns could include yyyy-MM-ddTHH:mm:ssXXX for 2015-03-15T15:02:37Z or 2015-03-15T15:02:37-05:00 , or HH:mm x for 15:02 -05 .

The delete: <a href="#dfn-cell-value" class="internalDFN"> insert: <a href="#dfn-value" class="internalDFN" data-link-type="dfn"> cell value will one or more dates/time values extracted using the format .

delete: <div class="note-title" aria-level="5" role="heading" id="h-note12"> insert: <div class="note-title" aria-level="5" role="heading" id="h-note15">
Note

For simplicity, this version of this standard does not support abbreviated or full month or day names, or double digit years. Future versions of this standard may support other date and time formats, or general purpose date/time pattern strings. Authors of schemas SHOULD use appropriate regular expressions, along with the string datatype, for dates and times that use a format other than that specified here.

6.4.5 Formats for durations

Durations MUST be formatted and interpreted as defined in [ xmlschema11-2 ], using the [ ISO8601 ] format -?P n Y n M n DT n H n M n S . For example, the duration P1Y1D is used for a year and a day; the duration PT2H30M for 2 hours and 30 minutes.

If the delete: <a href="#dfn-datatype-base" class="internalDFN"> insert: <a href="#dfn-base" class="internalDFN" data-link-type="dfn"> datatype base is a duration type, the delete: <a href="#dfn-datatype-format" class="internalDFN"> insert: <a href="#dfn-format" class="internalDFN" data-link-type="dfn"> datatype format annotation provides a regular expression for the string values, with syntax and processing defined by [ ECMASCRIPT ]. If the supplied value is not a valid regular expression, implementations MUST issue a warning and proceed as if no format had been provided.

delete: <div class="note-title" aria-level="5" role="heading" id="h-note13"> insert: <div class="note-title" aria-level="5" role="heading" id="h-note16">
Note

Authors are encouraged to be conservative in the regular expressions that they use, sticking to the basic features of regular expressions that are likely to be supported across implementations.

The delete: <a href="#dfn-cell-value" class="internalDFN"> insert: <a href="#dfn-value" class="internalDFN" data-link-type="dfn"> cell value will be one or more durations extracted using the format .

6.4.6 Formats for other types

If the delete: <a href="#dfn-datatype-base" class="internalDFN"> insert: <a href="#dfn-base" class="internalDFN" data-link-type="dfn"> datatype base is not numeric, boolean , a date/time type, or a duration type, the delete: <a href="#dfn-datatype-format" class="internalDFN"> insert: <a href="#dfn-format" class="internalDFN" data-link-type="dfn"> datatype format annotation provides a regular expression for the string values, with syntax and processing defined by [ ECMASCRIPT ]. If the supplied value is not a valid regular expression, implementations MUST issue a warning and proceed as if no format had been provided.

delete: <div class="note-title" aria-level="5" role="heading" id="h-note14"> insert: <div class="note-title" aria-level="5" role="heading" id="h-note17">
Note

Authors are encouraged to be conservative in the regular expressions that they use, sticking to the basic features of regular expressions that are likely to be supported across implementations.

Values that are labelled as html , xml , or json SHOULD NOT be validated against those formats.

delete: <div class="note-title" aria-level="5" role="heading" id="h-note15"> insert: <div class="note-title" aria-level="5" role="heading" id="h-note18">
Note

Metadata creators who wish to check the syntax of HTML, XML, or JSON within tabular data should use the delete: <a href="#dfn-datatype-format" class="internalDFN"> insert: <a href="#dfn-format" class="internalDFN" data-link-type="dfn"> datatype format annotation to specify a regular expression against which such values will be tested.

6.5 Presenting Tables

This section is non-normative.

When presenting tables, implementations should:

6.5.1 Bidirectional Tables

There are two levels of bidirectionality to consider when displaying tables: the directionality of the table (i.e., whether the columns should be arranged left-to-right or right-to-left) and the directionality of the content of individual cells.

The delete: <a href="#dfn-table-direction" class="internalDFN"> insert: <a href="#dfn-table-direction" class="internalDFN" data-link-type="dfn"> table direction annotation on the table provides information about the desired display of the columns in the table. If delete: <a href="#dfn-table-direction" class="internalDFN"> insert: <a href="#dfn-table-direction" class="internalDFN" data-link-type="dfn"> table direction is ltr then the first column should be displayed on the left and the last column on the right. If delete: <a href="#dfn-table-direction" class="internalDFN"> insert: <a href="#dfn-table-direction" class="internalDFN" data-link-type="dfn"> table direction is rtl then the first column should be displayed on the right and the last column on the left.

If delete: <a href="#dfn-table-direction" class="internalDFN"> insert: <a href="#dfn-table-direction" class="internalDFN" data-link-type="dfn"> table direction is auto then tables should be displayed with attention to the bidirectionality of the content of the cells in the table. Specifically, the values of the cells in the table should be scanned breadth first: from the first cell in the first column through to the last cell in the first row, down to the last cell in the last column. If the first character in the table with a strong type as defined in [ BIDI ] indicates a RTL directionality, the table should be displayed with the first column on the right and the last column on the left. Otherwise, the table should be displayed with the first column on the left and the last column on the right. Characters such as whitespace, quotes, commas, and numbers do not have a strong type, and therefore are skipped when identifying the character that determines the directionality of the table.

Implementations should enable user preferences to override the indicated metadata about the directionality of the table.

Once the directionality of the table has been determined, each cell within the table should be considered as a separate paragraph , as defined by the Unicode Bidirectional Algorithm ( UBA ) in [ BIDI ]. The directionality for the cell is determined by looking at the delete: <a title="cell text direction" href="#dfn-cell-text-direction" class="internalDFN"> insert: <a data-lt="cell text direction" href="#dfn-cell-text-direction" class="internalDFN" data-link-type="dfn"> text direction annotation for the cell, as follows:

  1. If the delete: <a title="cell text direction" href="#dfn-cell-text-direction" class="internalDFN"> insert: <a data-lt="cell text direction" href="#dfn-cell-text-direction" class="internalDFN" data-link-type="dfn"> text direction is ltr then the base direction for the cell content should be set to left-to-right.
  2. If the delete: <a title="cell text direction" href="#dfn-cell-text-direction" class="internalDFN"> insert: <a data-lt="cell text direction" href="#dfn-cell-text-direction" class="internalDFN" data-link-type="dfn"> text direction is rtl then the base direction for the cell content should be set to right-to-left.
  3. If the delete: <a title="cell text direction" href="#dfn-cell-text-direction" class="internalDFN"> insert: <a data-lt="cell text direction" href="#dfn-cell-text-direction" class="internalDFN" data-link-type="dfn"> text direction is auto then the base direction for the cell content should be set to the direction determined by the first character in the cell with a strong type as defined in [ BIDI ].
delete: <div class="note-title" aria-level="5" role="heading" id="h-note16"> insert: <div class="note-title" aria-level="5" role="heading" id="h-note19">
Note

If the delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#cell-textDirection" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#cell-textDirection" class="externalDFN"> textDirection property in metadata has the value "inherit" , the delete: <a title="cell text direction" href="#dfn-cell-text-direction" class="internalDFN"> insert: <a data-lt="cell text direction" href="#dfn-cell-text-direction" class="internalDFN" data-link-type="dfn"> text direction annotation for a cell inherits its value from the delete: <a href="#dfn-table-direction" class="internalDFN"> insert: <a href="#dfn-table-direction" class="internalDFN" data-link-type="dfn"> table direction annotation on the table.

When the delete: <a title="column titles" href="#dfn-column-titles" class="internalDFN"> insert: <a data-lt="column titles" href="#dfn-column-titles" class="internalDFN" data-link-type="dfn"> titles of a column are displayed, these should be displayed in the direction determined by the first character in the title with a strong type as defined in [ BIDI ]. Titles for the same column in different languages may be displayed in different directions.

6.5.2 Column and row labelling

The labelling of columns and rows helps those who are attempting to understand the content of a table to grasp what a particular cell means. Implementations should present appropriate titles for columns, and ensure that the most important information in a row is kept apparent to the user, to aid their understanding. For example:

  • a table presented on the screen might retain certain columns in view so that readers can easily glance at the identifying information in each row
  • as the user moves focus into a cell, screen readers announce a label for the new column if the user has changed column, or for the new row if the user has changed row

When labelling a column, either on the screen or aurally, implementations should use the first available of:

  1. the column's delete: <a title="column titles" href="#dfn-column-titles" class="internalDFN"> insert: <a data-lt="column titles" href="#dfn-column-titles" class="internalDFN" data-link-type="dfn"> titles in the preferred language of the user, or with an undefined language if there is no title available in a preferred language; there may be multiple such titles in which case all should be announced
  2. the column's delete: <a title="column name" href="#dfn-column-name" class="internalDFN"> insert: <a data-lt="column name" href="#dfn-name" class="internalDFN" data-link-type="dfn"> name
  3. the column's delete: <a title="column number" href="#dfn-column-number" class="internalDFN"> insert: <a data-lt="column number" href="#dfn-column-number" class="internalDFN" data-link-type="dfn"> number

When labelling a row, either on the screen or aurally, implementations should use the first available of:

  1. the row's delete: <a title="row titles" href="#dfn-row-titles" class="internalDFN"> insert: <a data-lt="row titles" href="#dfn-row-titles" class="internalDFN" data-link-type="dfn"> titles in the preferred language of the user, or with an undefined language if there is no title available in a preferred language; there may be multiple such titles in which case all should be announced
  2. the delete: <a title="cell value" href="#dfn-cell-value" class="internalDFN"> insert: <a data-lt="cell value" href="#dfn-values" class="internalDFN" data-link-type="dfn"> values of the cells in the row's delete: <a title="row primary key" href="#dfn-row-primary-key" class="internalDFN"> insert: <a data-lt="row primary key" href="#dfn-primary-key" class="internalDFN" data-link-type="dfn"> primary key
  3. the row's delete: <a title="row number" href="#dfn-row-number" class="internalDFN"> insert: <a data-lt="row number" href="#dfn-row-number" class="internalDFN" data-link-type="dfn"> number

6.6 Validating Tables

delete: <dfn id="dfn-validators"> insert: <dfn data-dfn-type="dfn" id="dfn-validators"> Validators test whether given delete: <a title="tabular data file" href="#dfn-tabular-data-file" class="internalDFN"> insert: <a data-lt="tabular data file" href="#dfn-tabular-data-files" class="internalDFN" data-link-type="dfn"> tabular data files adhere to the structure defined within a delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dfn-schema" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dfn-schema" class="externalDFN"> schema . Validators MUST raise errors (and halt processing) and issue warnings (and continue processing) as defined in [ tabular-metadata ]. In addition, validators MUST raise errors but MAY continue validating in the following situations:

6.7 Converting Tables

Conversions of tabular data to other formats operate over a delete: <a href="#dfn-annotated-table" class="internalDFN"> insert: <a href="#dfn-annotated-table" class="internalDFN" data-link-type="dfn"> annotated table constructed as defined in delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#annotating-tables"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#annotating-tables"> Annotating Tables in [ tabular-metadata ]. The mechanics of these conversions to other formats are defined in other specifications such as [ csv2json ] and [ csv2rdf ].

Conversion specifications MUST define a default mapping from an annotated table that lacks any annotations (i.e., that is equivalent to an un-annotated table).

Conversion specifications MUST use the delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dfn-inherited-property" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dfn-inherited-properties" class="externalDFN"> property value of the delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#cell-propertyUrl"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#cell-propertyUrl"> propertyUrl of a column as the basis for naming machine-readable fields in the target format, such as the name of the equivalent element or attribute in XML, property in JSON or property URI in RDF.

Conversion specifications MAY use any of the delete: <a title="annotation" href="#dfn-annotation" class="internalDFN"> insert: <a href="#dfn-annotations" class="internalDFN" data-link-type="dfn"> annotations found on an annotated table group, table, column, row or cell, including non-core annotations, to adjust the mapping into another format.

Conversion specifications MAY define additional annotations, not defined in this specification, which are specifically used when converting to the target format of the conversion. For example, a conversion to XML might specify a http://example.org/conversion/xml/element-or-attribute property on columns that determines whether a particular column is represented through an element or an attribute in the data.

7. Best Practice CSV

This section is non-normative.

There is no standard for CSV, and there are many variants of CSV used on the web today. This section defines a method for expressing tabular data adhering to the delete: <a href="#dfn-annotated-tabular-data-model" class="internalDFN"> insert: <a href="#dfn-annotated-tabular-data-model" class="internalDFN" data-link-type="dfn"> annotated tabular data model in CSV. Authors are encouraged to adhere to the constraints described in this section as implementations should process such CSV files consistently.

delete: <div class="note-title" aria-level="3" role="heading" id="h-note17"> insert: <div class="note-title" aria-level="3" role="heading" id="h-note20">
Note

This syntax is not compliant with text/csv as defined in [ RFC4180 ] in that it permits line endings other than CRLF . Supporting LF line endings is important for data formats that are used on non-Windows platforms. However, all files that adhere to [ RFC4180 ]'s definition of CSV meet the constraints described in this section.

Developing a standard for CSV is outside the scope of the Working Group. The details here aim to help shape any future standard.

7.1 Content Type

The appropriate content type for a CSV file is text/csv . For example, when a CSV file is transmitted via HTTP, the HTTP response should include a Content-Type header with the value text/csv :

 Content-Type: text/csv 

7.2 Encoding

CSV files should be encoded using UTF-8. UTF-8, and should be in Unicode Normal Form C as defined in [ insert: <cite> insert: <a class="bibref" href="#bib-UAX15"> UAX15 insert: </a> insert: </cite> ]. If a CSV file is not encoded using UTF-8, the encoding should be specified through the charset parameter in the Content-Type header:

 Content-Type: text/csv;charset=ISO-8859-1 

7.3 Line Endings

The ends of rows in a CSV file should be CRLF ( U+000D U+000A ) but may be LF ( U+000A ). Line endings within escaped delete: <a title="cell" href="#dfn-cell" class="internalDFN"> insert: <a href="#dfn-cell" class="internalDFN" data-link-type="dfn"> cells are not normalised.

7.4 Lines

Each line of a CSV file should contain the same number of comma-separated values.

Values that contain commas, line endings, or double quotes should be escaped by having the entire value wrapped in double quotes. There should not be whitespace before or after the double quotes. Within these escaped cells, any double quotes should be escaped with two double quotes ( "" ).

7.4.1 Headers

The first line of a CSV file should contain a comma-separated list of names of delete: <a title="column" href="#dfn-column" class="internalDFN"> insert: <a href="#dfn-column" class="internalDFN" data-link-type="dfn"> columns . This is known as the delete: <dfn id="dfn-header-line"> insert: <dfn data-dfn-type="dfn" id="dfn-header-line"> header line and provides titles for the columns. There are no constraints on these titles.

If a CSV file does not include a header line, this should be specified using the header parameter of the media type:

 Content-Type: text/csv;header=absent 

7.5 Grammar

This grammar is a generalization of that defined in [ RFC4180 ] and is included for reference only.

The EBNF used here is defined in XML 1.0 [ EBNF-NOTATION ].

[1] csv ::= header record +
[2] header ::= record
[3] record ::= fields #x0D ? #x0A
[4] fields ::= field (" , " fields ) *
[5] field ::= WS * rawfield WS *
[6] rawfield ::= ' " ' QCHAR * ' " ' | SCHAR *
[7] QCHAR ::= [ ^" ] | ' "" '
[8] SCHAR ::= [ ^", #x0A #x0D ]
[9] WS ::= [ #x20 #x09 ]

8. Parsing Tabular Data

This section is non-normative.

As described in section 7. Best Practice CSV , there may be many formats which an application might interpret into the tabular data model described in section 4. Tabular Data Models , including using different separators or fixed format tables, multiple tables within a single file, or ones that have metadata lines before a table header.

delete: <div class="note-title" aria-level="3" role="heading" id="h-note18"> insert: <div class="note-title" aria-level="3" role="heading" id="h-note21">
Note

Standardizing the parsing of CSV is outside the chartered scope of the Working Group. This non-normative section is intended to help the creators of parsers handle the wide variety of CSV-based formats that they may encounter due to the current lack of standardization of the format.

This section describes an algorithm for parsing formats that do not adhere to the constraints described in section 7. Best Practice CSV , as well as those that do, and extracting delete: <a href="#dfn-embedded-metadata" class="internalDFN"> insert: <a href="#dfn-embedding-metadata" class="internalDFN" data-link-type="dfn"> embedded metadata . The parsing algorithm uses the following flags. These may be set by metadata properties found while Locating Metadata , including through user input (see Overriding Metadata ), or through the inclusion of a delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dfn-dialect-description" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dfn-dialect-description" class="externalDFN"> dialect description within a metadata file:

delete: <dfn id="dfn-comment-prefix"> insert: <dfn data-dfn-type="dfn" id="dfn-comment-prefix"> comment prefix
A string that, when it appears at the beginning of a row, indicates that the row is a comment that should be associated as a rdfs:comment annotation to the table. This is set by the delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dialect-commentPrefix"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dialect-commentPrefix"> commentPrefix property of a delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dfn-dialect-description" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dfn-dialect-description" class="externalDFN"> dialect description . The default is null , which means no rows are treated as comments. A value other than null may mean that the delete: <a title="row source number" href="#dfn-row-source-number" class="internalDFN"> insert: <a data-lt="row source number" href="#dfn-row-source-number" class="internalDFN" data-link-type="dfn"> source numbers of delete: <a title="row" href="#dfn-row" class="internalDFN"> insert: <a href="#dfn-row" class="internalDFN" data-link-type="dfn"> rows are different from their delete: <a title="row number" href="#dfn-row-number" class="internalDFN"> insert: <a data-lt="row number" href="#dfn-row-number" class="internalDFN" data-link-type="dfn"> numbers .
delete: <dfn id="dfn-delimiter"> insert: <dfn data-dfn-type="dfn" id="dfn-delimiter"> delimiter
The separator between cells, set by the delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dialect-delimiter"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dialect-delimiter"> delimiter property of a delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dfn-dialect-description" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dfn-dialect-description" class="externalDFN"> dialect description . The default is , .
delete: <dfn id="dfn-encoding"> insert: <dfn data-dfn-type="dfn" id="dfn-encoding"> encoding
The character encoding for the file, one of the encodings listed in [ encoding ], set by the delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dialect-encoding"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dialect-encoding"> encoding property of a delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dfn-dialect-description" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dfn-dialect-description" class="externalDFN"> dialect description . The default is utf-8 .
delete: <dfn id="dfn-escape-character"> insert: <dfn data-dfn-type="dfn" id="dfn-escape-character"> escape character
The string that is used to escape the delete: <a href="#dfn-quote-character" class="internalDFN"> insert: <a href="#dfn-quote-character" class="internalDFN" data-link-type="dfn"> quote character within escaped cells, or null , set by the delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dialect-doubleQuote"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dialect-doubleQuote"> doubleQuote property of a delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dfn-dialect-description" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dfn-dialect-description" class="externalDFN"> dialect description . The default is " (such that "" is used to escape " within an escaped cell).
delete: <dfn id="dfn-header-row-count"> insert: <dfn data-dfn-type="dfn" id="dfn-header-row-count"> header row count
The number of delete: <dfn title="header row" id="dfn-header-row"> insert: <dfn data-dfn-type="dfn" id="dfn-header-rows"> header rows (following the skipped rows) in the file, set by the delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dialect-header"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dialect-header"> header or delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dialect-headerRowCount"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dialect-headerRowCount"> headerRowCount property of a delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dfn-dialect-description" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dfn-dialect-description" class="externalDFN"> dialect description . The default is 1 . A value other than 0 will mean that the delete: <a title="row source number" href="#dfn-row-source-number" class="internalDFN"> insert: <a data-lt="row source number" href="#dfn-row-source-number" class="internalDFN" data-link-type="dfn"> source numbers of delete: <a title="row" href="#dfn-row" class="internalDFN"> insert: <a href="#dfn-row" class="internalDFN" data-link-type="dfn"> rows will be different from their delete: <a title="row number" href="#dfn-row-number" class="internalDFN"> insert: <a data-lt="row number" href="#dfn-row-number" class="internalDFN" data-link-type="dfn"> numbers .
delete: <dfn id="dfn-line-terminators"> insert: <dfn data-dfn-type="dfn" id="dfn-line-terminators"> line terminators
The strings that can be used at the end of a row, set by the delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dialect-lineTerminators"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dialect-lineTerminators"> lineTerminators property of a delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dfn-dialect-description" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dfn-dialect-description" class="externalDFN"> dialect description . The default is [CRLF, LF] .
delete: <dfn id="dfn-quote-character"> insert: <dfn data-dfn-type="dfn" id="dfn-quote-character"> quote character
The string that is used around escaped cells, or null , set by the delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dialect-quoteChar"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dialect-quoteChar"> quoteChar property of a delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dfn-dialect-description" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dfn-dialect-description" class="externalDFN"> dialect description . The default is " .
delete: <dfn id="dfn-skip-blank-rows"> insert: <dfn data-dfn-type="dfn" id="dfn-skip-blank-rows"> skip blank rows
Indicates whether to ignore wholly empty rows (i.e. rows in which all the cells are empty), set by the delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dialect-skipBlankRows"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dialect-skipBlankRows"> skipBlankRows property of a delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dfn-dialect-description" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dfn-dialect-description" class="externalDFN"> dialect description . The default is false . A value other than false may mean that the delete: <a title="row source number" href="#dfn-row-source-number" class="internalDFN"> insert: <a data-lt="row source number" href="#dfn-row-source-number" class="internalDFN" data-link-type="dfn"> source numbers of delete: <a title="row" href="#dfn-row" class="internalDFN"> insert: <a href="#dfn-row" class="internalDFN" data-link-type="dfn"> rows are different from their delete: <a title="row number" href="#dfn-row-number" class="internalDFN"> insert: <a data-lt="row number" href="#dfn-row-number" class="internalDFN" data-link-type="dfn"> numbers .
delete: <dfn id="dfn-skip-columns"> insert: <dfn data-dfn-type="dfn" id="dfn-skip-columns"> skip columns
The number of columns to skip at the beginning of each row, set by the delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dialect-skipColumns"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dialect-skipColumns"> skipColumns property of a delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dfn-dialect-description" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dfn-dialect-description" class="externalDFN"> dialect description . The default is 0 . A value other than 0 will mean that the delete: <a title="column source number" href="#dfn-column-source-number" class="internalDFN"> insert: <a data-lt="column source number" href="#dfn-column-source-number" class="internalDFN" data-link-type="dfn"> source numbers of delete: <a title="column" href="#dfn-column" class="internalDFN"> insert: <a href="#dfn-column" class="internalDFN" data-link-type="dfn"> columns will be different from their delete: <a title="column number" href="#dfn-column-number" class="internalDFN"> insert: <a data-lt="column number" href="#dfn-column-number" class="internalDFN" data-link-type="dfn"> numbers .
delete: <dfn id="dfn-skip-rows"> insert: <dfn data-dfn-type="dfn" id="dfn-skip-rows"> skip rows
The number of rows to skip at the beginning of the file, before a header row or tabular data, set by the delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dialect-skipRows"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dialect-skipRows"> skipRows property of a delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dfn-dialect-description" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dfn-dialect-description" class="externalDFN"> dialect description . The default is 0 . A value greater than 0 will mean that the delete: <a title="row source number" href="#dfn-row-source-number" class="internalDFN"> insert: <a data-lt="row source number" href="#dfn-row-source-number" class="internalDFN" data-link-type="dfn"> source numbers of delete: <a title="row" href="#dfn-row" class="internalDFN"> insert: <a href="#dfn-row" class="internalDFN" data-link-type="dfn"> rows will be different from their delete: <a title="row number" href="#dfn-row-number" class="internalDFN"> insert: <a data-lt="row number" href="#dfn-row-number" class="internalDFN" data-link-type="dfn"> numbers .
delete: <dfn id="dfn-trim"> insert: <dfn data-dfn-type="dfn" id="dfn-trim"> trim
Indicates whether to trim whitespace around cells; may be true , false , start , or end , set by the delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dialect-skipInitialSpace"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dialect-skipInitialSpace"> skipInitialSpace or delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dialect-trim"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dialect-trim"> trim property of a delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dfn-dialect-description" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dfn-dialect-description" class="externalDFN"> dialect description . The default is true .

The algorithm for using these flags to parse a document containing tabular data to create a basic delete: <a href="#dfn-annotated-tabular-data-model" class="internalDFN"> insert: <a href="#dfn-annotated-tabular-data-model" class="internalDFN" data-link-type="dfn"> annotated tabular data model and to extract delete: <a href="#dfn-embedded-metadata" class="internalDFN"> insert: <a href="#dfn-embedding-metadata" class="internalDFN" data-link-type="dfn"> embedded metadata is as follows:

  1. Create a new delete: <a href="#dfn-table" class="internalDFN"> insert: <a href="#dfn-table" class="internalDFN" data-link-type="dfn"> table T with the annotations:
    • delete: <a title="table columns" href="#dfn-table-columns" class="internalDFN"> insert: <a data-lt="table columns" href="#dfn-column" class="internalDFN" data-link-type="dfn"> columns set to an empty list
    • delete: <a title="table rows" href="#dfn-table-rows" class="internalDFN"> insert: <a data-lt="table rows" href="#dfn-row" class="internalDFN" data-link-type="dfn"> rows set to an empty list
    • delete: <a title="table id" href="#dfn-table-id" class="internalDFN"> insert: <a data-lt="table id" href="#dfn-table-id" class="internalDFN" data-link-type="dfn"> id set to null
    • delete: <a title="table url" href="#dfn-table-url" class="internalDFN"> insert: <a data-lt="table url" href="#dfn-url" class="internalDFN" data-link-type="dfn"> url set to the location of the file, if known, or null
    • delete: <a href="#dfn-table-direction" class="internalDFN"> insert: <a href="#dfn-table-direction" class="internalDFN" data-link-type="dfn"> table direction set to auto
    • delete: <a title="table suppress output" href="#dfn-table-suppress-output" class="internalDFN"> insert: <a data-lt="table suppress output" href="#dfn-table-suppress-output" class="internalDFN" data-link-type="dfn"> suppress output set to false
    • delete: <a title="table notes" href="#dfn-table-notes" class="internalDFN"> insert: <a data-lt="table notes" href="#dfn-notes" class="internalDFN" data-link-type="dfn"> notes set to false
    • delete: <a title="table foreign keys" href="#dfn-table-foreign-keys" class="internalDFN"> insert: <a href="#dfn-foreign-keys" class="internalDFN" data-link-type="dfn"> foreign keys set to an empty list
    • delete: <a title="table transformations" href="#dfn-table-transformations" class="internalDFN"> insert: <a data-lt-nodefault="" data-lt="table transformations" href="#dfn-transformations" class="internalDFN" data-link-type="dfn"> transformations set to an empty list
  2. Create a metadata document structure M that looks like:
      {     "@context"   :     "http://www.w3.org/ns/csvw"   ,     "rdfs:comment"   :     []     "tableSchema"   :     {     "columns"   :     []     }     }    
  3. If the URL of the delete: <a href="#dfn-tabular-data-file" class="internalDFN"> insert: <a href="#dfn-tabular-data-files" class="internalDFN" data-link-type="dfn"> tabular data file being parsed is known, set the url property on M to that URL.
  4. Set delete: <dfn id="dfn-source-row-number"> insert: <dfn data-dfn-type="dfn" id="dfn-source-row-number"> source row number to 1 .
  5. Read the file using the delete: <a href="#dfn-encoding" class="internalDFN"> insert: <a href="#dfn-encoding" class="internalDFN" data-link-type="dfn"> encoding , as specified in [ encoding ], using the replacement error mode . If the encoding is not a Unicode encoding, use a normalizing transcoder to normalize into Unicode Normal Form C as defined in [ UAX15 ].

    delete: <div class="note-title" aria-level="3" role="heading" id="h-note19"> insert: <div class="note-title" aria-level="3" role="heading" id="h-note22">
    Note

    The replacement error mode ensures that any non-Unicode characters within the CSV file are replaced by U+FFFD, ensuring that strings within the tabular data model such as column titles and cell string values only contain valid Unicode characters.

  6. Repeat the following the number of times indicated by delete: <a href="#dfn-skip-rows" class="internalDFN"> insert: <a href="#dfn-skip-rows" class="internalDFN" data-link-type="dfn"> skip rows :
    1. delete: <a href="#dfn-read-a-row" class="internalDFN"> insert: <a href="#dfn-read-a-row" class="internalDFN" data-link-type="dfn"> Read a row to provide the delete: <a href="#dfn-row-content" class="internalDFN"> insert: <a href="#dfn-row-content" class="internalDFN" data-link-type="dfn"> row content .
    2. If the delete: <a href="#dfn-comment-prefix" class="internalDFN"> insert: <a href="#dfn-comment-prefix" class="internalDFN" data-link-type="dfn"> comment prefix is not null and the delete: <a href="#dfn-row-content" class="internalDFN"> insert: <a href="#dfn-row-content" class="internalDFN" data-link-type="dfn"> row content begins with the delete: <a href="#dfn-comment-prefix" class="internalDFN"> insert: <a href="#dfn-comment-prefix" class="internalDFN" data-link-type="dfn"> comment prefix , strip that prefix from the delete: <a href="#dfn-row-content" class="internalDFN"> insert: <a href="#dfn-row-content" class="internalDFN" data-link-type="dfn"> row content , and add the resulting string to the M .rdfs:comment array.
    3. Otherwise, if the delete: <a href="#dfn-row-content" class="internalDFN"> insert: <a href="#dfn-row-content" class="internalDFN" data-link-type="dfn"> row content is not an empty string, add the delete: <a href="#dfn-row-content" class="internalDFN"> insert: <a href="#dfn-row-content" class="internalDFN" data-link-type="dfn"> row content to the M .rdfs:comment array.
    4. Add 1 to the delete: <a href="#dfn-source-row-number" class="internalDFN"> insert: <a href="#dfn-source-row-number" class="internalDFN" data-link-type="dfn"> source row number .
  7. Repeat the following the number of times indicated by delete: <a href="#dfn-header-row-count" class="internalDFN"> insert: <a href="#dfn-header-row-count" class="internalDFN" data-link-type="dfn"> header row count :
    1. delete: <a href="#dfn-read-a-row" class="internalDFN"> insert: <a href="#dfn-read-a-row" class="internalDFN" data-link-type="dfn"> Read a row to provide the delete: <a href="#dfn-row-content" class="internalDFN"> insert: <a href="#dfn-row-content" class="internalDFN" data-link-type="dfn"> row content .
    2. If the delete: <a href="#dfn-comment-prefix" class="internalDFN"> insert: <a href="#dfn-comment-prefix" class="internalDFN" data-link-type="dfn"> comment prefix is not null and the delete: <a href="#dfn-row-content" class="internalDFN"> insert: <a href="#dfn-row-content" class="internalDFN" data-link-type="dfn"> row content begins with the delete: <a href="#dfn-comment-prefix" class="internalDFN"> insert: <a href="#dfn-comment-prefix" class="internalDFN" data-link-type="dfn"> comment prefix , strip that prefix from the delete: <a href="#dfn-row-content" class="internalDFN"> insert: <a href="#dfn-row-content" class="internalDFN" data-link-type="dfn"> row content , and add the resulting string to the M .rdfs:comment array.
    3. Otherwise, delete: <a title="parse a row" href="#dfn-parse-a-row" class="internalDFN"> insert: <a href="#dfn-parse-a-row" class="internalDFN" data-link-type="dfn"> parse the row to provide a delete: <a href="#dfn-list-of-cell-values" class="internalDFN"> insert: <a href="#dfn-list-of-cell-values" class="internalDFN" data-link-type="dfn"> list of cell values , and:
      1. Remove the first delete: <a href="#dfn-skip-columns" class="internalDFN"> insert: <a href="#dfn-skip-columns" class="internalDFN" data-link-type="dfn"> skip columns number of values from the delete: <a href="#dfn-list-of-cell-values" class="internalDFN"> insert: <a href="#dfn-list-of-cell-values" class="internalDFN" data-link-type="dfn"> list of cell values .
      2. For each of the remaining values at index i in the delete: <a href="#dfn-list-of-cell-values" class="internalDFN"> insert: <a href="#dfn-list-of-cell-values" class="internalDFN" data-link-type="dfn"> list of cell values :
        1. If the value at index i in the delete: <a href="#dfn-list-of-cell-values" class="internalDFN"> insert: <a href="#dfn-list-of-cell-values" class="internalDFN" data-link-type="dfn"> list of cell values is an empty string or consists only of whitespace, do nothing.
        2. Otherwise, if there is no column description object at index i in M .tableSchema.columns , create a new one with a title property whose value is an array containing a single value that is the value at index i in the delete: <a href="#dfn-list-of-cell-values" class="internalDFN"> insert: <a href="#dfn-list-of-cell-values" class="internalDFN" data-link-type="dfn"> list of cell values .
        3. Otherwise, add the value at index i in the delete: <a href="#dfn-list-of-cell-values" class="internalDFN"> insert: <a href="#dfn-list-of-cell-values" class="internalDFN" data-link-type="dfn"> list of cell values to the array at M .tableSchema.columns[ i ].title .
    4. Add 1 to the delete: <a href="#dfn-source-row-number" class="internalDFN"> insert: <a href="#dfn-source-row-number" class="internalDFN" data-link-type="dfn"> source row number .
  8. If delete: <a href="#dfn-header-row-count" class="internalDFN"> insert: <a href="#dfn-header-row-count" class="internalDFN" data-link-type="dfn"> header row count is zero, create an empty column description object in M .tableSchema.columns for each column in the current row after delete: <a href="#dfn-skip-columns" class="internalDFN"> insert: <a href="#dfn-skip-columns" class="internalDFN" data-link-type="dfn"> skip columns .
  9. Set delete: <dfn title="model row number" id="dfn-model-row-number"> insert: <dfn data-lt-nodefault="" data-dfn-type="dfn" id="dfn-model-row-number"> row number to 1 .
  10. While it is possible to read another row, do the following:
    1. Set the delete: <dfn id="dfn-source-column-number"> insert: <dfn data-dfn-type="dfn" id="dfn-source-column-number"> source column number to 1 .
    2. delete: <a href="#dfn-read-a-row" class="internalDFN"> insert: <a href="#dfn-read-a-row" class="internalDFN" data-link-type="dfn"> Read a row to provide the delete: <a href="#dfn-row-content" class="internalDFN"> insert: <a href="#dfn-row-content" class="internalDFN" data-link-type="dfn"> row content .
    3. If the delete: <a href="#dfn-comment-prefix" class="internalDFN"> insert: <a href="#dfn-comment-prefix" class="internalDFN" data-link-type="dfn"> comment prefix is not null and the delete: <a href="#dfn-row-content" class="internalDFN"> insert: <a href="#dfn-row-content" class="internalDFN" data-link-type="dfn"> row content begins with the delete: <a href="#dfn-comment-prefix" class="internalDFN"> insert: <a href="#dfn-comment-prefix" class="internalDFN" data-link-type="dfn"> comment prefix , strip that prefix from the delete: <a href="#dfn-row-content" class="internalDFN"> insert: <a href="#dfn-row-content" class="internalDFN" data-link-type="dfn"> row content , and add the resulting string to the M .rdfs:comment array.
    4. Otherwise, delete: <a title="parse a row" href="#dfn-parse-a-row" class="internalDFN"> insert: <a href="#dfn-parse-a-row" class="internalDFN" data-link-type="dfn"> parse the row to provide a delete: <a href="#dfn-list-of-cell-values" class="internalDFN"> insert: <a href="#dfn-list-of-cell-values" class="internalDFN" data-link-type="dfn"> list of cell values , and:
      1. If all of the values in the delete: <a href="#dfn-list-of-cell-values" class="internalDFN"> insert: <a href="#dfn-list-of-cell-values" class="internalDFN" data-link-type="dfn"> list of cell values are empty strings, and delete: <a href="#dfn-skip-blank-rows" class="internalDFN"> insert: <a href="#dfn-skip-blank-rows" class="internalDFN" data-link-type="dfn"> skip blank rows is true , add 1 to the delete: <a href="#dfn-source-row-number" class="internalDFN"> insert: <a href="#dfn-source-row-number" class="internalDFN" data-link-type="dfn"> source row number and move on to process the next row.
      2. Otherwise, create a new delete: <a href="#dfn-row" class="internalDFN"> insert: <a href="#dfn-row" class="internalDFN" data-link-type="dfn"> row R , with:
        • delete: <a title="row table" href="#dfn-row-table" class="internalDFN"> insert: <a data-lt-nodefault="" data-lt="row table" href="#dfn-row-table" class="internalDFN" data-link-type="dfn"> table set to T
        • delete: <a title="row number" href="#dfn-row-number" class="internalDFN"> insert: <a data-lt="row number" href="#dfn-row-number" class="internalDFN" data-link-type="dfn"> number set to delete: <a title="model row number" href="#dfn-model-row-number" class="internalDFN"> insert: <a data-lt="model row number" href="#dfn-row-number" class="internalDFN" data-link-type="dfn"> row number
        • delete: <a title="row source number" href="#dfn-row-source-number" class="internalDFN"> insert: <a data-lt="row source number" href="#dfn-row-source-number" class="internalDFN" data-link-type="dfn"> source number set to delete: <a href="#dfn-source-row-number" class="internalDFN"> insert: <a href="#dfn-source-row-number" class="internalDFN" data-link-type="dfn"> source row number
        • delete: <a title="row primary key" href="#dfn-row-primary-key" class="internalDFN"> insert: <a data-lt="row primary key" href="#dfn-primary-key" class="internalDFN" data-link-type="dfn"> primary key set to an empty list
        • delete: <a title="row referenced rows" href="#dfn-row-referenced-rows" class="internalDFN"> insert: <a data-lt="row referenced rows" href="#dfn-referenced-rows" class="internalDFN" data-link-type="dfn"> referenced rows set to an empty list
        • delete: <a title="row cells" href="#dfn-row-cells" class="internalDFN"> insert: <a data-lt="row cells" href="#dfn-cell" class="internalDFN" data-link-type="dfn"> cells set to an empty list
      3. Append R to the delete: <a title="table rows" href="#dfn-table-rows" class="internalDFN"> insert: <a data-lt="table rows" href="#dfn-row" class="internalDFN" data-link-type="dfn"> rows of delete: <a href="#dfn-table" class="internalDFN"> insert: <a href="#dfn-table" class="internalDFN" data-link-type="dfn"> table T .
      4. Remove the first delete: <a href="#dfn-skip-columns" class="internalDFN"> insert: <a href="#dfn-skip-columns" class="internalDFN" data-link-type="dfn"> skip columns number of values from the delete: <a href="#dfn-list-of-cell-values" class="internalDFN"> insert: <a href="#dfn-list-of-cell-values" class="internalDFN" data-link-type="dfn"> list of cell values and add that number to the delete: <a href="#dfn-source-column-number" class="internalDFN"> insert: <a href="#dfn-source-column-number" class="internalDFN" data-link-type="dfn"> source column number .
      5. For each of the remaining values at index i in the delete: <a href="#dfn-list-of-cell-values" class="internalDFN"> insert: <a href="#dfn-list-of-cell-values" class="internalDFN" data-link-type="dfn"> list of cell values (where i starts at 1 ):
        1. Identify the delete: <a href="#dfn-column" class="internalDFN"> insert: <a href="#dfn-column" class="internalDFN" data-link-type="dfn"> column C at index i within the delete: <a title="table columns" href="#dfn-table-columns" class="internalDFN"> insert: <a data-lt="table columns" href="#dfn-column" class="internalDFN" data-link-type="dfn"> columns of delete: <a href="#dfn-table" class="internalDFN"> insert: <a href="#dfn-table" class="internalDFN" data-link-type="dfn"> table T . If there is no such column:
          1. Create a new delete: <a href="#dfn-column" class="internalDFN"> insert: <a href="#dfn-column" class="internalDFN" data-link-type="dfn"> column C with:
            • delete: <a title="column table" href="#dfn-column-table" class="internalDFN"> insert: <a data-lt="column table" href="#dfn-table" class="internalDFN" data-link-type="dfn"> table set to T
            • delete: <a title="column number" href="#dfn-column-number" class="internalDFN"> insert: <a data-lt="column number" href="#dfn-column-number" class="internalDFN" data-link-type="dfn"> number set to i
            • delete: <a title="column source number" href="#dfn-column-source-number" class="internalDFN"> insert: <a data-lt="column source number" href="#dfn-column-source-number" class="internalDFN" data-link-type="dfn"> source number set to delete: <a href="#dfn-source-column-number" class="internalDFN"> insert: <a href="#dfn-source-column-number" class="internalDFN" data-link-type="dfn"> source column number
            • delete: <a title="column name" href="#dfn-column-name" class="internalDFN"> insert: <a data-lt="column name" href="#dfn-name" class="internalDFN" data-link-type="dfn"> name set to null
            • delete: <a title="column titles" href="#dfn-column-titles" class="internalDFN"> insert: <a data-lt="column titles" href="#dfn-column-titles" class="internalDFN" data-link-type="dfn"> titles set to an empty list
            • delete: <a title="column virtual" href="#dfn-column-virtual" class="internalDFN"> insert: <a data-lt="column virtual" href="#dfn-virtual" class="internalDFN" data-link-type="dfn"> virtual set to false
            • delete: <a title="column suppress output" href="#dfn-column-suppress-output" class="internalDFN"> insert: <a data-lt="column suppress output" href="#dfn-column-suppress-output" class="internalDFN" data-link-type="dfn"> suppress output set to false
            • delete: <a title="column datatype" href="#dfn-column-datatype" class="internalDFN"> insert: <a data-lt="column datatype" href="#dfn-datatype" class="internalDFN" data-link-type="dfn"> datatype set to string
            • delete: <a title="column default" href="#dfn-column-default" class="internalDFN"> insert: <a data-lt="column default" href="#dfn-default" class="internalDFN" data-link-type="dfn"> default set to an empty string
            • delete: <a title="column lang" href="#dfn-column-lang" class="internalDFN"> insert: <a data-lt="column lang" href="#dfn-lang" class="internalDFN" data-link-type="dfn"> lang set to und
            • delete: <a title="column null" href="#dfn-column-null" class="internalDFN"> insert: <a data-lt="column null" href="#dfn-null" class="internalDFN" data-link-type="dfn"> null set to an empty string
            • delete: <a title="column ordered" href="#dfn-column-ordered" class="internalDFN"> insert: <a data-lt="column ordered" href="#dfn-column-ordered" class="internalDFN" data-link-type="dfn"> ordered set to false
            • delete: <a title="column required" href="#dfn-column-required" class="internalDFN"> insert: <a data-lt="column required" href="#dfn-required" class="internalDFN" data-link-type="dfn"> required set to false
            • delete: <a title="column separator" href="#dfn-column-separator" class="internalDFN"> insert: <a data-lt="column separator" href="#dfn-separator" class="internalDFN" data-link-type="dfn"> separator set to null
            • delete: <a title="column text direction" href="#dfn-column-text-direction" class="internalDFN"> insert: <a data-lt="column text direction" href="#dfn-column-text-direction" class="internalDFN" data-link-type="dfn"> text direction set to auto
            • delete: <a title="column about URL" href="#dfn-column-about-url" class="internalDFN"> insert: <a data-lt-nodefault="" data-lt="column about URL" href="#dfn-column-about-url" class="internalDFN" data-link-type="dfn"> about URL set to null
            • delete: <a title="column property URL" href="#dfn-column-property-url" class="internalDFN"> insert: <a data-lt-nodefault="" data-lt="column property URL" href="#dfn-column-property-url" class="internalDFN" data-link-type="dfn"> property URL set to null
            • delete: <a title="column value URL" href="#dfn-column-value-url" class="internalDFN"> insert: <a data-lt-nodefault="" data-lt="column value URL" href="#dfn-column-value-url" class="internalDFN" data-link-type="dfn"> value URL set to null
            • delete: <a title="column cells" href="#dfn-column-cells" class="internalDFN"> insert: <a data-lt="column cells" href="#dfn-cell" class="internalDFN" data-link-type="dfn"> cells set to an empty list
          2. Append C to the delete: <a title="table columns" href="#dfn-table-columns" class="internalDFN"> insert: <a data-lt="table columns" href="#dfn-column" class="internalDFN" data-link-type="dfn"> columns of delete: <a href="#dfn-table" class="internalDFN"> insert: <a href="#dfn-table" class="internalDFN" data-link-type="dfn"> table T (at index i ).
        2. Create a new delete: <a href="#dfn-cell" class="internalDFN"> insert: <a href="#dfn-cell" class="internalDFN" data-link-type="dfn"> cell D , with:
          • delete: <a title="cell table" href="#dfn-cell-table" class="internalDFN"> insert: <a data-lt="cell table" href="#dfn-table" class="internalDFN" data-link-type="dfn"> table set to T
          • delete: <a title="cell column" href="#dfn-cell-column" class="internalDFN"> insert: <a data-lt="cell column" href="#dfn-column" class="internalDFN" data-link-type="dfn"> column set to C
          • delete: <a title="cell row" href="#dfn-cell-row" class="internalDFN"> insert: <a data-lt="cell row" href="#dfn-row" class="internalDFN" data-link-type="dfn"> row set to R
          • delete: <a title="cell string value" href="#dfn-cell-string-value" class="internalDFN"> insert: <a data-lt="cell string value" href="#dfn-string-value" class="internalDFN" data-link-type="dfn"> string value set to the value at index i in the delete: <a href="#dfn-list-of-cell-values" class="internalDFN"> insert: <a href="#dfn-list-of-cell-values" class="internalDFN" data-link-type="dfn"> list of cell values
          • delete: <a title="cell value" href="#dfn-cell-value" class="internalDFN"> insert: <a data-lt="cell value" href="#dfn-value" class="internalDFN" data-link-type="dfn"> value set to the value at index i in the delete: <a href="#dfn-list-of-cell-values" class="internalDFN"> insert: <a href="#dfn-list-of-cell-values" class="internalDFN" data-link-type="dfn"> list of cell values
          • delete: <a title="cell errors" href="#dfn-cell-errors" class="internalDFN"> insert: <a data-lt="cell errors" href="#dfn-errors" class="internalDFN" data-link-type="dfn"> errors set to an empty list
          • delete: <a title="cell text direction" href="#dfn-cell-text-direction" class="internalDFN"> insert: <a data-lt="cell text direction" href="#dfn-cell-text-direction" class="internalDFN" data-link-type="dfn"> text direction set to auto
          • delete: <a title="cell ordered" href="#dfn-cell-ordered" class="internalDFN"> insert: <a data-lt="cell ordered" href="#dfn-cell-ordered" class="internalDFN" data-link-type="dfn"> ordered set to false
          • delete: <a title="cell about URL" href="#dfn-cell-about-url" class="internalDFN"> insert: <a data-lt-nodefault="" data-lt="cell about URL" href="#dfn-cell-about-url" class="internalDFN" data-link-type="dfn"> about URL set to null
          • delete: <a title="cell property URL" href="#dfn-cell-property-url" class="internalDFN"> insert: <a data-lt="cell property URL" href="#dfn-cell-property-url" class="internalDFN" data-link-type="dfn"> property URL set to null
          • delete: <a title="cell value URL" href="#dfn-cell-value-url" class="internalDFN"> insert: <a data-lt-nodefault="" data-lt="cell value URL" href="#dfn-cell-value-url" class="internalDFN" data-link-type="dfn"> value URL set to null
        3. Append delete: <a href="#dfn-cell" class="internalDFN"> insert: <a href="#dfn-cell" class="internalDFN" data-link-type="dfn"> cell D to the delete: <a title="column cells" href="#dfn-column-cells" class="internalDFN"> insert: <a data-lt="column cells" href="#dfn-cell" class="internalDFN" data-link-type="dfn"> cells of delete: <a href="#dfn-column" class="internalDFN"> insert: <a href="#dfn-column" class="internalDFN" data-link-type="dfn"> column C .
        4. Append delete: <a href="#dfn-cell" class="internalDFN"> insert: <a href="#dfn-cell" class="internalDFN" data-link-type="dfn"> cell D to the delete: <a title="row cells" href="#dfn-row-cells" class="internalDFN"> insert: <a data-lt="row cells" href="#dfn-cell" class="internalDFN" data-link-type="dfn"> cells of delete: <a href="#dfn-row" class="internalDFN"> insert: <a href="#dfn-row" class="internalDFN" data-link-type="dfn"> row R (at index i ).
        5. Add 1 to the delete: <a href="#dfn-source-column-number" class="internalDFN"> insert: <a href="#dfn-source-column-number" class="internalDFN" data-link-type="dfn"> source column number .
    5. Add 1 to the delete: <a href="#dfn-source-row-number" class="internalDFN"> insert: <a href="#dfn-source-row-number" class="internalDFN" data-link-type="dfn"> source row number .
  11. If M .rdfs:comment is an empty array, remove the rdfs:comment property from M .
  12. Return the delete: <a href="#dfn-table" class="internalDFN"> insert: <a href="#dfn-table" class="internalDFN" data-link-type="dfn"> table T and the delete: <a href="#dfn-embedded-metadata" class="internalDFN"> insert: <a href="#dfn-embedding-metadata" class="internalDFN" data-link-type="dfn"> embedded metadata M .

To delete: <dfn id="dfn-read-a-row"> insert: <dfn data-dfn-type="dfn" id="dfn-read-a-row"> read a row to provide delete: <dfn id="dfn-row-content"> insert: <dfn data-dfn-type="dfn" id="dfn-row-content"> row content , perform the following steps:

  1. Set the delete: <a href="#dfn-row-content" class="internalDFN"> insert: <a href="#dfn-row-content" class="internalDFN" data-link-type="dfn"> row content to an empty string.
  2. Read initial characters and process as follows:
    1. If the string starts with the delete: <a href="#dfn-escape-character" class="internalDFN"> insert: <a href="#dfn-escape-character" class="internalDFN" data-link-type="dfn"> escape character followed by the delete: <a href="#dfn-quote-character" class="internalDFN"> insert: <a href="#dfn-quote-character" class="internalDFN" data-link-type="dfn"> quote character , append both strings to the delete: <a href="#dfn-row-content" class="internalDFN"> insert: <a href="#dfn-row-content" class="internalDFN" data-link-type="dfn"> row content , and move on to process the string following the delete: <a href="#dfn-quote-character" class="internalDFN"> insert: <a href="#dfn-quote-character" class="internalDFN" data-link-type="dfn"> quote character .
    2. Otherwise, if the string starts with the delete: <a href="#dfn-escape-character" class="internalDFN"> insert: <a href="#dfn-escape-character" class="internalDFN" data-link-type="dfn"> escape character and the delete: <a href="#dfn-escape-character" class="internalDFN"> insert: <a href="#dfn-escape-character" class="internalDFN" data-link-type="dfn"> escape character is not the same as the delete: <a href="#dfn-quote-character" class="internalDFN"> insert: <a href="#dfn-quote-character" class="internalDFN" data-link-type="dfn"> quote character , append the delete: <a href="#dfn-escape-character" class="internalDFN"> insert: <a href="#dfn-escape-character" class="internalDFN" data-link-type="dfn"> escape character and the single character following it to the delete: <a href="#dfn-row-content" class="internalDFN"> insert: <a href="#dfn-row-content" class="internalDFN" data-link-type="dfn"> row content and move on to process the string following that character.
    3. Otherwise, if the string starts with the delete: <a href="#dfn-quote-character" class="internalDFN"> insert: <a href="#dfn-quote-character" class="internalDFN" data-link-type="dfn"> quote character , append the delete: <a href="#dfn-quoted-value" class="internalDFN"> insert: <a href="#dfn-quoted-value" class="internalDFN" data-link-type="dfn"> quoted value obtained by delete: <a title="read a quoted value" href="#dfn-read-a-quoted-value" class="internalDFN"> insert: <a data-lt="read a quoted value" href="#dfn-read-a-quoted-value" class="internalDFN" data-link-type="dfn"> reading a quoted value to the delete: <a href="#dfn-row-content" class="internalDFN"> insert: <a href="#dfn-row-content" class="internalDFN" data-link-type="dfn"> row content and move on to process the string following the quoted value.
    4. Otherwise, if the string starts with one of the delete: <a href="#dfn-line-terminators" class="internalDFN"> insert: <a href="#dfn-line-terminators" class="internalDFN" data-link-type="dfn"> line terminators , return the delete: <a href="#dfn-row-content" class="internalDFN"> insert: <a href="#dfn-row-content" class="internalDFN" data-link-type="dfn"> row content .
    5. Otherwise, append the first character to the delete: <a href="#dfn-row-content" class="internalDFN"> insert: <a href="#dfn-row-content" class="internalDFN" data-link-type="dfn"> row content and move on to process the string following that character.
  3. If there are no more characters to read, return the delete: <a href="#dfn-row-content" class="internalDFN"> insert: <a href="#dfn-row-content" class="internalDFN" data-link-type="dfn"> row content .

To delete: <dfn id="dfn-read-a-quoted-value"> insert: <dfn data-dfn-type="dfn" id="dfn-read-a-quoted-value"> read a quoted value to provide a delete: <dfn id="dfn-quoted-value"> insert: <dfn data-dfn-type="dfn" id="dfn-quoted-value"> quoted value , perform the following steps:

  1. Set the delete: <a href="#dfn-quoted-value" class="internalDFN"> insert: <a href="#dfn-quoted-value" class="internalDFN" data-link-type="dfn"> quoted value to an empty string.
  2. Read the initial delete: <a href="#dfn-quote-character" class="internalDFN"> insert: <a href="#dfn-quote-character" class="internalDFN" data-link-type="dfn"> quote character and add a delete: <a href="#dfn-quote-character" class="internalDFN"> insert: <a href="#dfn-quote-character" class="internalDFN" data-link-type="dfn"> quote character to the delete: <a href="#dfn-quoted-value" class="internalDFN"> insert: <a href="#dfn-quoted-value" class="internalDFN" data-link-type="dfn"> quoted value .
  3. Read initial characters and process as follows:
    1. If the string starts with the delete: <a href="#dfn-escape-character" class="internalDFN"> insert: <a href="#dfn-escape-character" class="internalDFN" data-link-type="dfn"> escape character followed by the delete: <a href="#dfn-quote-character" class="internalDFN"> insert: <a href="#dfn-quote-character" class="internalDFN" data-link-type="dfn"> quote character , append both strings to the delete: <a href="#dfn-quoted-value" class="internalDFN"> insert: <a href="#dfn-quoted-value" class="internalDFN" data-link-type="dfn"> quoted value , and move on to process the string following the delete: <a href="#dfn-quote-character" class="internalDFN"> insert: <a href="#dfn-quote-character" class="internalDFN" data-link-type="dfn"> quote character .
    2. Otherwise, if string starts with the delete: <a href="#dfn-escape-character" class="internalDFN"> insert: <a href="#dfn-escape-character" class="internalDFN" data-link-type="dfn"> escape character and the delete: <a href="#dfn-escape-character" class="internalDFN"> insert: <a href="#dfn-escape-character" class="internalDFN" data-link-type="dfn"> escape character is not the same as the delete: <a href="#dfn-quote-character" class="internalDFN"> insert: <a href="#dfn-quote-character" class="internalDFN" data-link-type="dfn"> quote character , append the delete: <a href="#dfn-escape-character" class="internalDFN"> insert: <a href="#dfn-escape-character" class="internalDFN" data-link-type="dfn"> escape character and the character following it to the delete: <a href="#dfn-quoted-value" class="internalDFN"> insert: <a href="#dfn-quoted-value" class="internalDFN" data-link-type="dfn"> quoted value and move on to process the string following that character.
    3. Otherwise, if the string starts with the delete: <a href="#dfn-quote-character" class="internalDFN"> insert: <a href="#dfn-quote-character" class="internalDFN" data-link-type="dfn"> quote character , return the delete: <a href="#dfn-quoted-value" class="internalDFN"> insert: <a href="#dfn-quoted-value" class="internalDFN" data-link-type="dfn"> quoted value .
    4. Otherwise, append the first character to the delete: <a href="#dfn-quoted-value" class="internalDFN"> insert: <a href="#dfn-quoted-value" class="internalDFN" data-link-type="dfn"> quoted value and move on to process the string following that character.

To delete: <dfn id="dfn-parse-a-row"> insert: <dfn data-dfn-type="dfn" id="dfn-parse-a-row"> parse a row to provide a delete: <dfn id="dfn-list-of-cell-values"> insert: <dfn data-dfn-type="dfn" id="dfn-list-of-cell-values"> list of cell values , perform the following steps:

  1. Set the delete: <a href="#dfn-list-of-cell-values" class="internalDFN"> insert: <a href="#dfn-list-of-cell-values" class="internalDFN" data-link-type="dfn"> list of cell values to an empty list and the delete: <dfn id="dfn-current-cell-value"> insert: <dfn data-dfn-type="dfn" id="dfn-current-cell-value"> current cell value to an empty string.
  2. Set the delete: <dfn id="dfn-quoted"> insert: <dfn data-dfn-type="dfn" id="dfn-quoted"> quoted flag to false .
  3. Read initial characters and process as follows:
    1. If the string starts with the delete: <a href="#dfn-escape-character" class="internalDFN"> insert: <a href="#dfn-escape-character" class="internalDFN" data-link-type="dfn"> escape character followed by the delete: <a href="#dfn-quote-character" class="internalDFN"> insert: <a href="#dfn-quote-character" class="internalDFN" data-link-type="dfn"> quote character , append the delete: <a href="#dfn-quote-character" class="internalDFN"> insert: <a href="#dfn-quote-character" class="internalDFN" data-link-type="dfn"> quote character to the delete: <a href="#dfn-current-cell-value" class="internalDFN"> insert: <a href="#dfn-current-cell-value" class="internalDFN" data-link-type="dfn"> current cell value , and move on to process the string following the delete: <a href="#dfn-quote-character" class="internalDFN"> insert: <a href="#dfn-quote-character" class="internalDFN" data-link-type="dfn"> quote character .
    2. Otherwise, if the string starts with the delete: <a href="#dfn-escape-character" class="internalDFN"> insert: <a href="#dfn-escape-character" class="internalDFN" data-link-type="dfn"> escape character and the delete: <a href="#dfn-escape-character" class="internalDFN"> insert: <a href="#dfn-escape-character" class="internalDFN" data-link-type="dfn"> escape character is not the same as the delete: <a href="#dfn-quote-character" class="internalDFN"> insert: <a href="#dfn-quote-character" class="internalDFN" data-link-type="dfn"> quote character , append the character following the delete: <a href="#dfn-escape-character" class="internalDFN"> insert: <a href="#dfn-escape-character" class="internalDFN" data-link-type="dfn"> escape character to the delete: <a href="#dfn-current-cell-value" class="internalDFN"> insert: <a href="#dfn-current-cell-value" class="internalDFN" data-link-type="dfn"> current cell value and move on to process the string following that character.
    3. Otherwise, if the string starts with the delete: <a href="#dfn-quote-character" class="internalDFN"> insert: <a href="#dfn-quote-character" class="internalDFN" data-link-type="dfn"> quote character then:
      1. If delete: <a href="#dfn-quoted" class="internalDFN"> insert: <a href="#dfn-quoted" class="internalDFN" data-link-type="dfn"> quoted is false , set the delete: <a href="#dfn-quoted" class="internalDFN"> insert: <a href="#dfn-quoted" class="internalDFN" data-link-type="dfn"> quoted flag to true , and move on to process the remaining string. If the delete: <a href="#dfn-current-cell-value" class="internalDFN"> insert: <a href="#dfn-current-cell-value" class="internalDFN" data-link-type="dfn"> current cell value is not an empty string, raise an error.
      2. Otherwise, set delete: <a href="#dfn-quoted" class="internalDFN"> insert: <a href="#dfn-quoted" class="internalDFN" data-link-type="dfn"> quoted to false , and move on to process the remaining string. If the remaining string does not start with the delete: <a href="#dfn-delimiter" class="internalDFN"> insert: <a href="#dfn-delimiter" class="internalDFN" data-link-type="dfn"> delimiter , raise an error.
    4. Otherwise, if the string starts with the delete: <a href="#dfn-delimiter" class="internalDFN"> insert: <a href="#dfn-delimiter" class="internalDFN" data-link-type="dfn"> delimiter , then:
      1. If delete: <a href="#dfn-quoted" class="internalDFN"> insert: <a href="#dfn-quoted" class="internalDFN" data-link-type="dfn"> quoted is true , append the delete: <a href="#dfn-delimiter" class="internalDFN"> insert: <a href="#dfn-delimiter" class="internalDFN" data-link-type="dfn"> delimiter string to the delete: <a href="#dfn-current-cell-value" class="internalDFN"> insert: <a href="#dfn-current-cell-value" class="internalDFN" data-link-type="dfn"> current cell value and move on to process the remaining string.
      2. Otherwise, delete: <a title="conditionally trim a cell value" href="#dfn-conditionally-trim-a-cell-value" class="internalDFN"> insert: <a data-lt="conditionally trim a cell value" href="#dfn-conditionally-trim-a-cell-value" class="internalDFN" data-link-type="dfn"> conditionally trim the delete: <a href="#dfn-current-cell-value" class="internalDFN"> insert: <a href="#dfn-current-cell-value" class="internalDFN" data-link-type="dfn"> current cell value , add the resulting delete: <a href="#dfn-trimmed-cell-value" class="internalDFN"> insert: <a href="#dfn-trimmed-cell-value" class="internalDFN" data-link-type="dfn"> trimmed cell value to the delete: <a href="#dfn-list-of-cell-values" class="internalDFN"> insert: <a href="#dfn-list-of-cell-values" class="internalDFN" data-link-type="dfn"> list of cell values and move on to process the following string.
    5. Otherwise, append the first character to the delete: <a href="#dfn-current-cell-value" class="internalDFN"> insert: <a href="#dfn-current-cell-value" class="internalDFN" data-link-type="dfn"> current cell value and move on to process the remaining string.
  4. If there are no more characters to read, delete: <a title="conditionally trim a cell value" href="#dfn-conditionally-trim-a-cell-value" class="internalDFN"> insert: <a data-lt="conditionally trim a cell value" href="#dfn-conditionally-trim-a-cell-value" class="internalDFN" data-link-type="dfn"> conditionally trim the delete: <a href="#dfn-current-cell-value" class="internalDFN"> insert: <a href="#dfn-current-cell-value" class="internalDFN" data-link-type="dfn"> current cell value , add the resulting delete: <a href="#dfn-trimmed-cell-value" class="internalDFN"> insert: <a href="#dfn-trimmed-cell-value" class="internalDFN" data-link-type="dfn"> trimmed cell value to the delete: <a href="#dfn-list-of-cell-values" class="internalDFN"> insert: <a href="#dfn-list-of-cell-values" class="internalDFN" data-link-type="dfn"> list of cell values and return the delete: <a href="#dfn-list-of-cell-values" class="internalDFN"> insert: <a href="#dfn-list-of-cell-values" class="internalDFN" data-link-type="dfn"> list of cell values .

To delete: <dfn id="dfn-conditionally-trim-a-cell-value"> insert: <dfn data-dfn-type="dfn" id="dfn-conditionally-trim-a-cell-value"> conditionally trim a cell value to provide a delete: <dfn id="dfn-trimmed-cell-value"> insert: <dfn data-dfn-type="dfn" id="dfn-trimmed-cell-value"> trimmed cell value , perform the following steps:

  1. Set the delete: <a href="#dfn-trimmed-cell-value" class="internalDFN"> insert: <a href="#dfn-trimmed-cell-value" class="internalDFN" data-link-type="dfn"> trimmed cell value to the provided cell value.
  2. If delete: <a href="#dfn-trim" class="internalDFN"> insert: <a href="#dfn-trim" class="internalDFN" data-link-type="dfn"> trim is true or start then remove any leading whitespace from the start of the delete: <a href="#dfn-trimmed-cell-value" class="internalDFN"> insert: <a href="#dfn-trimmed-cell-value" class="internalDFN" data-link-type="dfn"> trimmed cell value and move on to the next step.
  3. If delete: <a href="#dfn-trim" class="internalDFN"> insert: <a href="#dfn-trim" class="internalDFN" data-link-type="dfn"> trim is true or end then remove any trailing whitespace from the end of the delete: <a href="#dfn-trimmed-cell-value" class="internalDFN"> insert: <a href="#dfn-trimmed-cell-value" class="internalDFN" data-link-type="dfn"> trimmed cell value and move on to the next step.
  4. Return the delete: <a href="#dfn-trimmed-cell-value" class="internalDFN"> insert: <a href="#dfn-trimmed-cell-value" class="internalDFN" data-link-type="dfn"> trimmed cell value .
delete: <div class="note-title" aria-level="3" role="heading" id="h-note20"> insert: <div class="note-title" aria-level="3" role="heading" id="h-note23">
Note

This parsing algorithm does not account for the possibility of there being more than one area of tabular data within a single CSV file.

8.1 Bidirectionality in CSV Files

This section is non-normative.

Bidirectional content does not alter the definition of rows or the assignment of cells to columns. Whether or not a CSV file contains right-to-left characters, the first column's content is the first cell of each row, which is the text prior to the first occurrence of a comma within that row.

For example, Egyptian Referendum results are available as a CSV file at https://egelections-2011.appspot.com/Referendum2012/results/csv/EG.csv . Over the wire and in non-Unicode-aware text editors, the CSV looks like:

  ‌ا‌ل‌م‌ح‌ا‌ف‌ظ‌ة‌,‌ن‌س‌ب‌ة‌ ‌م‌و‌ا‌ف‌ق‌,‌ن‌س‌ب‌ة‌ ‌غ‌ي‌ر‌ ‌م‌و‌ا‌ف‌ق‌,‌ع‌د‌د‌ ‌ا‌ل‌ن‌ا‌خ‌ب‌ي‌ن‌,‌ا‌ل‌أ‌ص‌و‌ا‌ت‌ ‌ا‌ل‌ص‌ح‌ي‌ح‌ة‌,‌ا‌ل‌أ‌ص‌و‌ا‌ت‌ ‌ا‌ل‌ب‌ا‌ط‌ل‌ة‌,‌ن‌س‌ب‌ة‌ ‌ا‌ل‌م‌ش‌ا‌ر‌ك‌ة‌,‌م‌و‌ا‌ف‌ق‌,‌غ‌ي‌ر‌ ‌م‌و‌ا‌ف‌ق‌ ‌ا‌ل‌ق‌ل‌ي‌و‌ب‌ي‌ة‌,60.0,40.0,"2,639,808","853,125","15,224",32.9,"512,055","341,070" ‌ا‌ل‌ج‌ي‌ز‌ة‌,66.7,33.3,"4,383,701","1,493,092","24,105",34.6,"995,417","497,675" ‌ا‌ل‌ق‌ا‌ه‌ر‌ة‌,43.2,56.8,"6,580,478","2,254,698","36,342",34.8,"974,371","1,280,327" ‌ق‌ن‌ا‌,84.5,15.5,"1,629,713","364,509","6,743",22.8,"307,839","56,670" ...  

Within this CSV file, the first column appears as the content of each line before the first comma and is named المحافظة (appearing at the start of each row as ‌ا‌ل‌م‌ح‌ا‌ف‌ظ‌ة‌ in the example, which is displaying the relevant characters from left to right in the order they appear "on the wire").

The CSV translates to a table model that looks like:

Column / Row column 1 column 2 column 3 column 4 column 5 column 6 column 7 column 8 column 9
column names المحافظة نسبة موافق نسبة غير موافق عدد الناخبين الأصوات الصحيحة الأصوات الباطلة نسبة المشاركة موافق غير موافق
row 1 القليوبية 60.0 40.0 2,639,808 853,125 15,224 32.9 512,055 341,070
row 2 الجيزة 66.7 33.3 4,383,701 1,493,092 24,105 34.6 995,417 497,675
row 3 القاهرة 43.2 56.8 6,580,478 2,254,698 36,342 34.8 974,371 1,280,327
row 4 قنا 84.5 15.5 1,629,713 364,509 6,743 22.8 307,839 56,670

The fragment identifier #col=3 identifies the third of the columns, named نسبة غير موافق (appearing as ‌ن‌س‌ب‌ة‌ ‌غ‌ي‌ر‌ ‌م‌و‌ا‌ف‌ق‌ in the example).

section 6.5.1 Bidirectional Tables defines how this table model should be displayed by compliant applications, and how metadata can affect the display. The default is for the display to be determined by the content of the table. For example, if this CSV were turned into an HTML table for display into a web page, it should be displayed with the first column on the right and the last on the left, as follows:

غير موافق موافق نسبة المشاركة الأصوات الباطلة الأصوات الصحيحة عدد الناخبين نسبة غير موافق نسبة موافق المحافظة
341,070 512,055 32.9 15,224 853,125 2,639,808 40.0 60.0 القليوبية
497,675 995,417 34.6 24,105 1,493,092 4,383,701 33.3 66.7 الجيزة
1,280,327 974,371 34.8 36,342 2,254,698 6,580,478 56.8 43.2 القاهرة
56,670 307,839 22.8 6,743 364,509 1,629,713 15.5 84.5 قنا

The fragment identifier #col=3 still identifies the third of the columns, named نسبة غير موافق , which appears in the HTML display as the third column from the right and is what those who read right-to-left would think of as the third column.

Note that this display matches that shown on the original website .

8.2 Examples

8.2.1 Simple Example

A simple CSV file that complies to the constraints described in section 7. Best Practice CSV , at http://example.org/tree-ops.csv , might look like:

Example 14 : http://example.org/tree-ops.csv
 GID,On Street,Species,Trim Cycle,Inventory Date 1,ADDISON AV,Celtis australis,Large Tree Routine Prune,10/18/2010 2,EMERSON ST,Liquidambar styraciflua,Large Tree Routine Prune,6/2/2010 

Parsing this file results in an delete: <a href="#dfn-annotated-tabular-data-model" class="internalDFN"> insert: <a href="#dfn-annotated-tabular-data-model" class="internalDFN" data-link-type="dfn"> annotated tabular data model of a single delete: <a href="#dfn-table" class="internalDFN"> insert: <a href="#dfn-table" class="internalDFN" data-link-type="dfn"> table T with five columns and two rows. The columns have the annotations shown in the following table:

id core annotations
table number source number cells titles
C1 T 1 1 C1.1 , C2.1 GID
C2 T 2 2 C1.2 , C2.2 On Street
C3 T 3 3 C1.3 , C2.3 Species
C4 T 4 4 C1.4 , C2.4 Trim Cycle
C5 T 5 5 C1.5 , C2.5 Inventory Date

The extracted delete: <a href="#dfn-embedded-metadata" class="internalDFN"> insert: <a href="#dfn-embedding-metadata" class="internalDFN" data-link-type="dfn"> embedded metadata , as defined in [ tabular-metadata ], would look like:

Example 15 : tree-ops.csv Embedded Metadata
  {     "@type"   :     "Table"   ,     "url"   :     "http://example.org/tree-ops.csv"   ,     "tableSchema"   :     {     "columns"   :     [     {   "titles"   :     [     "GID"     ]},     {   "titles"   :     [     "On Street"     ]},     {   "titles"   :     [     "Species"     ]},     {   "titles"   :     [     "Trim Cycle"     ]},     {   "titles"   :     [     "Inventory Date"     ]}     ]     }     }  

The rows have the annotations shown in the following table:

id core annotations
table number source number cells
R1 T 1 2 C1.1 , C1.2 , C1.3 , C1.4 , C1.5
R2 T 2 3 C2.1 , C2.2 , C2.3 , C2.4 , C2.5
delete: <div class="note-title" aria-level="5" role="heading" id="h-note21"> insert: <div class="note-title" aria-level="5" role="heading" id="h-note24">
Note

The delete: <a title="row source number" href="#dfn-row-source-number" class="internalDFN"> insert: <a data-lt="row source number" href="#dfn-row-source-number" class="internalDFN" data-link-type="dfn"> source number of each row is offset by one from the delete: <a title="row number" href="#dfn-row-number" class="internalDFN"> insert: <a data-lt="row number" href="#dfn-row-number" class="internalDFN" data-link-type="dfn"> number of each row because in the source CSV file, the header line is the first line. It is possible to reconstruct a [ RFC7111 ] compliant reference to the first record in the original CSV file ( http://example.org/tree-ops.csv#row=2 ) using the value of the row's source number. This enables implementations to retain provenance between the table model and the original file.

The cells have the annotations shown in the following table (note that the delete: <a title="cell value" href="#dfn-cell-value" class="internalDFN"> insert: <a data-lt="cell value" href="#dfn-values" class="internalDFN" data-link-type="dfn"> values of all the cells in the table are strings, denoted by the double quotes in the table below):

id core annotations
table column row string value value
C1.1 T C1 R1 "1" "1"
C1.2 T C2 R1 "ADDISON AV" "ADDISON AV"
C1.3 T C3 R1 "Celtis australis" "Celtis australis"
C1.4 T C4 R1 "Large Tree Routine Prune" "Large Tree Routine Prune"
C1.5 T C5 R1 "10/18/2010" "10/18/2010"
C2.1 T C1 R2 "2" "2"
C2.2 T C2 R2 "EMERSON ST" "EMERSON ST"
C2.3 T C3 R2 "Liquidambar styraciflua" "Liquidambar styraciflua"
C2.4 T C4 R2 "Large Tree Routine Prune" "Large Tree Routine Prune"
C2.5 T C5 R2 "6/2/2010" "6/2/2010"
8.2.1.1 Using Overriding Metadata

The tools that the consumer of this data uses may provide a mechanism for overriding the metadata that has been provided within the file itself. For example, they might enable the consumer to add machine-readable names to the columns, or to mark the fifth column as holding a date in the format M/D/YYYY . These facilities are implementation defined; the code for invoking a Javascript-based parser might look like:

Example 16 : Javascript implementation configuration
  data   .   parse   ({     "column-names"   :     [   "GID"   ,     "on_street"   ,     "species"   ,     "trim_cycle"   ,     "inventory_date"   ],     "datatypes"   :     [   "string"   ,     "string"   ,     "string"   ,     "string"   ,     "date"   ],     "formats"   :     [   null   ,   null   ,   null   ,   null   ,   "M/D/YYYY"   ]     });  

This is equivalent to a metadata file expressed in the syntax defined in [ tabular-metadata ], looking like:

Example 17 : Equivalent metadata syntax
  {     "@type"   :     "Table"   ,     "url"   :     "http://example.org/tree-ops.csv"   ,     "tableSchema"   :     {     "columns"   :     [{     "name"   :     "GID"   ,     "datatype"   :     "string"     },     {     "name"   :     "on_street"   ,     "datatype"   :     "string"     },     {     "name"   :     "species"   ,     "datatype"   :     "string"     },     {     "name"   :     "trim_cycle"   ,     "datatype"   :     "string"     },     {     "name"   :     "inventory_date"   ,     "datatype"   :     {     "base"   :     "date"   ,     "format"   :     "M/d/yyyy"     }     }]     }     }  

This would be merged with the delete: <a href="#dfn-embedded-metadata" class="internalDFN"> insert: <a href="#dfn-embedding-metadata" class="internalDFN" data-link-type="dfn"> embedded metadata found in the CSV file, providing the titles for the columns to create:

Example 18 : Merged metadata
  {     "@type"   :     "Table"   ,     "url"   :     "http://example.org/tree-ops.csv"   ,     "tableSchema"   :     {     "columns"   :     [{     "name"   :     "GID"   ,     "titles"   :     "GID"   ,     "datatype"   :     "string"     },     {     "name"   :     "on_street"   ,     "titles"   :     "On Street"   ,     "datatype"   :     "string"     },     {     "name"   :     "species"   ,     "titles"   :     "Species"   ,     "datatype"   :     "string"     },     {     "name"   :     "trim_cycle"   ,     "titles"   :     "Trim Cycle"   ,     "datatype"   :     "string"     },     {     "name"   :     "inventory_date"   ,     "titles"   :     "Inventory Date"   ,     "datatype"   :     {     "base"   :     "date"   ,     "format"   :     "M/d/yyyy"     }     }]     }     }  

The processor can then create an delete: <a href="#dfn-annotated-tabular-data-model" class="internalDFN"> insert: <a href="#dfn-annotated-tabular-data-model" class="internalDFN" data-link-type="dfn"> annotated tabular data model that included name annotations on the columns, and datatype annotations on the cells, and created cells whose delete: <a title="cell value" href="#dfn-cell-value" class="internalDFN"> insert: <a data-lt="cell value" href="#dfn-values" class="internalDFN" data-link-type="dfn"> values were of appropriate types (in the case of this Javascript implementation, the cells in the last column would be Date objects, for example).

Assuming this kind of implementation-defined parsing, the columns would then have the annotations shown in the following table:

id core annotations
table number source number cells name titles datatype
C1 T 1 1 C1.1 , C2.1 GID GID string
C2 T 2 2 C1.2 , C2.2 on_street On Street string
C3 T 3 3 C1.3 , C2.3 species Species string
C4 T 4 4 C1.4 , C2.4 trim_cycle Trim Cycle string
C5 T 5 5 C1.5 , C2.5 inventory_date Inventory Date { "base": "date", "format": "M/d/yyyy" }

The cells have the annotations shown in the following table. Because of the overrides provided by the consumer to guide the parsing, and the way the parser works, the cells in the Inventory Date column (cells C1.5 and C2.5 ) have delete: <a title="cell value" href="#dfn-cell-value" class="internalDFN"> insert: <a data-lt="cell value" href="#dfn-values" class="internalDFN" data-link-type="dfn"> values that are parsed dates rather than unparsed strings.

id core annotations
table column row string value value
C1.1 T C1 R1 "1" "1"
C1.2 T C2 R1 "ADDISON AV" "ADDISON AV"
C1.3 T C3 R1 "Celtis australis" "Celtis australis"
C1.4 T C4 R1 "Large Tree Routine Prune" "Large Tree Routine Prune"
C1.5 T C5 R1 "10/18/2010" 2010-10-18
C2.1 T C1 R2 "2" "2"
C2.2 T C2 R2 "EMERSON ST" "EMERSON ST"
C2.3 T C3 R2 "Liquidambar styraciflua" "Liquidambar styraciflua"
C2.4 T C4 R2 "Large Tree Routine Prune" "Large Tree Routine Prune"
C2.5 T C5 R2 "6/2/2010" 2010-06-02
8.2.1.2 Using a Metadata File

A similar set of annotations could be provided through a metadata file, located as discussed in section 5. Locating Metadata and defined in [ tabular-metadata ]. For example, this might look like:

Example 19 : http://example.org/tree-ops.csv-metadata.json
  {     "@context"   :     [   "http://www.w3.org/ns/csvw"   ,     {   "@language"   :     "en"   }],     "url"   :     "tree-ops.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"   },     "tableSchema"   :     {     "columns"   :     [{     "name"   :     "GID"   ,     "titles"   :     [   "GID"   ,     "Generic Identifier"   ],     "dc:description"   :     "An identifier for the operation on a tree."   ,     "datatype"   :     "string"   ,     "required"   :     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"     },     {     "name"   :     "inventory_date"   ,     "titles"   :     "Inventory Date"   ,     "dc:description"   :     "The date of the operation that was performed."   ,     "datatype"   :     {   "base"   :     "date"   ,     "format"   :     "M/d/yyyy"   }     }],     "primaryKey"   :     "GID"   ,     "aboutUrl"   :     "#gid-{GID}"     }     }  

The delete: <a href="#dfn-annotated-tabular-data-model" class="internalDFN"> insert: <a href="#dfn-annotated-tabular-data-model" class="internalDFN" data-link-type="dfn"> annotated tabular data model generated from this would be more sophisticated again. The delete: <a href="#dfn-table" class="internalDFN"> insert: <a href="#dfn-table" class="internalDFN" data-link-type="dfn"> table itself would have the following annotations:

dc:title
{"@value": "Tree Operations", "@language": "en"}
dcat:keyword
[{"@value": "tree", "@language", "en"}, {"@value": "street", "@language": "en"}, {"@value": "maintenance", "@language": "en"}]
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": "date"}

The columns would have the annotations shown in the following table:

id core annotations other annotations
table number source number cells name titles datatype dc:description
C1 T 1 1 C1.1 , C2.1 GID GID , Generic Identifier string An identifier for the operation on a tree.
C2 T 2 2 C1.2 , C2.2 on_street On Street string The street that the tree is on.
C3 T 3 3 C1.3 , C2.3 species Species string The species of the tree.
C4 T 4 4 C1.4 , C2.4 trim_cycle Trim Cycle string The operation performed on the tree.
C5 T 5 5 C1.5 , C2.5 inventory_date Inventory Date { "base": "date", "format": "M/d/yyyy" } The date of the operation that was performed.

The rows have an additional delete: <a title="row primary key" href="#dfn-row-primary-key" class="internalDFN"> insert: <a data-lt="row primary key" href="#dfn-primary-key" class="internalDFN" data-link-type="dfn"> primary key annotation, as shown in the following table:

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.1
R2 T 2 3 C2.1 , C2.2 , C2.3 , C2.4 , C2.5 C2.1

Thanks to the provided metadata, the cells again have the annotations shown in the following table. The metadata file has provided the information to supplement the model with additional annotations but also, for the Inventory Date column (cells C1.5 and C2.5 ), have a delete: <a title="cell value" href="#dfn-cell-value" class="internalDFN"> insert: <a data-lt="cell value" href="#dfn-value" class="internalDFN" data-link-type="dfn"> value that is a parsed date rather than an unparsed string.

id core annotations
table column row string value value about URL
C1.1 T C1 R1 "1" "1" http://example.org/tree-ops.csv#gid-1
C1.2 T C2 R1 "ADDISON AV" "ADDISON AV" http://example.org/tree-ops.csv#gid-1
C1.3 T C3 R1 "Celtis australis" "Celtis australis" http://example.org/tree-ops.csv#gid-1
C1.4 T C4 R1 "Large Tree Routine Prune" "Large Tree Routine Prune" http://example.org/tree-ops.csv#gid-1
C1.5 T C5 R1 "10/18/2010" 2010-10-18 http://example.org/tree-ops.csv#gid-1
C2.1 T C1 R2 "2" "2" http://example.org/tree-ops.csv#gid-2
C2.2 T C2 R2 "EMERSON ST" "EMERSON ST" http://example.org/tree-ops.csv#gid-2
C2.3 T C3 R2 "Liquidambar styraciflua" "Liquidambar styraciflua" http://example.org/tree-ops.csv#gid-2
C2.4 T C4 R2 "Large Tree Routine Prune" "Large Tree Routine Prune" http://example.org/tree-ops.csv#gid-2
C2.5 T C5 R2 "6/2/2010" 2010-06-02 http://example.org/tree-ops.csv#gid-2

8.2.2 Empty and Quoted Cells

The following slightly amended CSV file contains quoted and missing cell values:

Example 20 : CSV file containing quoted and missing cell values
 GID,On Street,Species,Trim Cycle,Inventory Date 1,ADDISON AV,"Celtis australis","Large Tree Routine Prune",10/18/2010 2,,"Liquidambar styraciflua","Large Tree Routine Prune", 

Parsing this file similarly results in an delete: <a href="#dfn-annotated-tabular-data-model" class="internalDFN"> insert: <a href="#dfn-annotated-tabular-data-model" class="internalDFN" data-link-type="dfn"> annotated tabular data model of a single delete: <a href="#dfn-table" class="internalDFN"> insert: <a href="#dfn-table" class="internalDFN" data-link-type="dfn"> table T with five columns and two rows. The columns and rows have exactly the same annotations as previously, but there are two null cell values for C2.2 and C2.5 . Note that the quoting of values within the CSV makes no difference to either the delete: <a title="cell string value" href="#dfn-cell-string-value" class="internalDFN"> insert: <a data-lt="cell string value" href="#dfn-string-value" class="internalDFN" data-link-type="dfn"> string value or delete: <a title="cell value" href="#dfn-cell-value" class="internalDFN"> insert: <a data-lt="cell value" href="#dfn-value" class="internalDFN" data-link-type="dfn"> value of the cell.

id core annotations
table column row string value value
C1.1 T C1 R1 "1" "1"
C1.2 T C2 R1 "ADDISON AV" "ADDISON AV"
C1.3 T C3 R1 "Celtis australis" "Celtis australis"
C1.4 T C4 R1 "Large Tree Routine Prune" "Large Tree Routine Prune"
C1.5 T C5 R1 "10/18/2010" "10/18/2010"
C2.1 T C1 R2 "2" "2"
C2.2 T C2 R2 "" null
C2.3 T C3 R2 "Liquidambar styraciflua" "Liquidambar styraciflua"
C2.4 T C4 R2 "Large Tree Routine Prune" "Large Tree Routine Prune"
C2.5 T C5 R2 "" null

8.2.3 Tabular Data Embedding Annotations

The following example illustrates some of the complexities that can be involved in parsing tabular data, how the flags described above can be used, and how new tabular data formats could be defined that embed additional annotations into the tabular data model.

In this example, the publishers of the data are using an internal convention to supply additional metadata about the tabular data embedded within the file itself. They are also using a tab as a separator rather than a comma.

Example 21 : Tab-separated file containing embedded metadata
 # publisher City of Palo Alto # updated 12/31/2010 #name GID on_street species trim_cycle inventory_date #datatype string string string string date:M/D/YYYY GID On Street Species Trim Cycle Inventory Date 1 ADDISON AV Celtis australis Large Tree Routine Prune 10/18/2010 2 EMERSON ST Liquidambar styraciflua Large Tree Routine Prune 6/2/2010 
8.2.3.1 Naive Parsing

Naive parsing of the above data will assume a comma separator and thus results in a single delete: <a href="#dfn-table" class="internalDFN"> insert: <a href="#dfn-table" class="internalDFN" data-link-type="dfn"> table T with a single column and six rows. The column has the annotations shown in the following table:

id core annotations
table number source number cells titles
C1 T 1 1 C1.1 , C2.1 , C3.1 , C4.1 , C5.1 # publisher City of Palo Alto

The rows have the annotations shown in the following table:

id core annotations
table number source number cells
R1 T 1 2 C1.1
R2 T 2 3 C2.1
R3 T 3 4 C3.1
R4 T 4 5 C4.1
R5 T 5 6 C5.1
R6 T 6 7 C6.1

The cells have the annotations shown in the following table (note that the delete: <a title="cell value" href="#dfn-cell-value" class="internalDFN"> insert: <a data-lt="cell value" href="#dfn-values" class="internalDFN" data-link-type="dfn"> values of all the cells in the table are strings, denoted by the double quotes in the table below):

id core annotations
table column row string value value
C1.1 T C1 R1 "# updated 12/31/2010" "# updated 12/31/2010"
C1.1 T C1 R1 "#name GID on_street species trim_cycle inventory_date" "#name GID on_street species trim_cycle inventory_date"
C2.1 T C1 R2 "#datatype string string string string date:M/D/YYYY" "#datatype string string string string date:M/D/YYYY"
C3.1 T C1 R3 " GID On Street Species Trim Cycle Inventory Date" " GID On Street Species Trim Cycle Inventory Date"
C4.1 T C1 R4 " 1 ADDISON AV Celtis australis Large Tree Routine Prune 10/18/2010" " 1 ADDISON AV Celtis australis Large Tree Routine Prune 10/18/2010"
C5.1 T C1 R5 " 2 EMERSON ST Liquidambar styraciflua Large Tree Routine Prune 6/2/2010" " 2 EMERSON ST Liquidambar styraciflua Large Tree Routine Prune 6/2/2010"
8.2.3.2 Parsing with Flags

The consumer of the data may use the flags described above to create a more useful set of data from this file. Specifically, they could set:

  • delete: <a href="#dfn-delimiter" class="internalDFN"> insert: <a href="#dfn-delimiter" class="internalDFN" data-link-type="dfn"> delimiter to a tab character
  • delete: <a href="#dfn-skip-rows" class="internalDFN"> insert: <a href="#dfn-skip-rows" class="internalDFN" data-link-type="dfn"> skip rows to 4
  • delete: <a href="#dfn-skip-columns" class="internalDFN"> insert: <a href="#dfn-skip-columns" class="internalDFN" data-link-type="dfn"> skip columns to 1
  • delete: <a href="#dfn-comment-prefix" class="internalDFN"> insert: <a href="#dfn-comment-prefix" class="internalDFN" data-link-type="dfn"> comment prefix to #

Setting these is done in an implementation-defined way. It could be done, for example, by sniffing the contents of the file itself, through command-line options, or by embedding a dialect description into a metadata file associated with the tabular data, which would look like:

Example 22 : Dialect description
  {     "delimiter"   :     "\t"   ,     "skipRows"   :     4   ,     "skipColumns"   :     1   ,     "commentPrefix"   :     "#"     }  

With these flags in operation, parsing this file results in an delete: <a href="#dfn-annotated-tabular-data-model" class="internalDFN"> insert: <a href="#dfn-annotated-tabular-data-model" class="internalDFN" data-link-type="dfn"> annotated tabular data model of a single delete: <a href="#dfn-table" class="internalDFN"> insert: <a href="#dfn-table" class="internalDFN" data-link-type="dfn"> table T with five columns and two rows which is largely the same as that created from the original simple example described in section 8.2.1 Simple Example . There are three differences.

First, because the four skipped rows began with the delete: <a href="#dfn-comment-prefix" class="internalDFN"> insert: <a href="#dfn-comment-prefix" class="internalDFN" data-link-type="dfn"> comment prefix , the table itself now has four rdfs:comment annotations, with the values:

  1. publisher City of Palo Alto
  2. updated 12/31/2010
  3. name GID on_street species trim_cycle inventory_date
  4. datatype string string string string date:M/D/YYYY

Second, because the first column has been skipped, the delete: <a title="column source number" href="#dfn-column-source-number" class="internalDFN"> insert: <a data-lt="column source number" href="#dfn-column-source-number" class="internalDFN" data-link-type="dfn"> source number of each of the columns is offset by one from the delete: <a title="column number" href="#dfn-column-number" class="internalDFN"> insert: <a data-lt="column number" href="#dfn-column-number" class="internalDFN" data-link-type="dfn"> number of each column:

id core annotations
table number source number cells titles
C1 T 1 2 C1.1 , C2.1 GID
C2 T 2 3 C1.2 , C2.2 On Street
C3 T 3 4 C1.3 , C2.3 Species
C4 T 4 5 C1.4 , C2.4 Trim Cycle
C5 T 5 6 C1.5 , C2.5 Inventory Date

Finally, because four additional rows have been skipped, the delete: <a title="row source number" href="#dfn-row-source-number" class="internalDFN"> insert: <a data-lt="row source number" href="#dfn-row-source-number" class="internalDFN" data-link-type="dfn"> source number of each of the rows is offset by five from the delete: <a href="#dfn-row-number" class="internalDFN"> insert: <a href="#dfn-row-number" class="internalDFN" data-link-type="dfn"> row number (the four skipped rows plus the single header row):

id core annotations
table number source number cells
R1 T 1 6 C1.1 , C1.2 , C1.3 , C1.4 , C1.5
R2 T 2 7 C2.1 , C2.2 , C2.3 , C2.4 , C2.5
8.2.3.3 Recognizing Tabular Data Formats

The conventions used in this data (invented for the purpose of this example) are in fact intended to create an delete: <a href="#dfn-annotated-tabular-data-model" class="internalDFN"> insert: <a href="#dfn-annotated-tabular-data-model" class="internalDFN" data-link-type="dfn"> annotated tabular data model which includes named annotations on the table itself, on the columns, and on the cells. The creator of these conventions could create a specification for this particular tabular data syntax and register a media type for it. The specification would include statements like:

  • A tab delimiter is always used.
  • The first column is always ignored.
  • When the first column of a row has the value "#" , the second column is the name of an annotation on the table and the values of the remaining columns are concatenated to create the value of that annotation.
  • When the first column of a row has the value #name , the remaining cells in the row provide a name annotation for each column in the table.
  • When the first column of a row has the value #datatype , the remaining cells in the row provide datatype / format annotations for the cells within the relevant column, and these are interpreted to create the delete: <a title="cell value" href="#dfn-cell-value" class="internalDFN"> insert: <a data-lt="cell value" href="#dfn-value" class="internalDFN" data-link-type="dfn"> value for each cell in that column.
  • The first row where the first column is empty is a row of headers; these provide title annotations on the columns in the table.
  • The remaining rows make up the data of the table.

Parsers that recognized the format could then build a more sophisticated annotated tabular data model using only the embedded information in the delete: <a href="#dfn-tabular-data-file" class="internalDFN"> insert: <a href="#dfn-tabular-data-files" class="internalDFN" data-link-type="dfn"> tabular data file . They would extract delete: <a href="#dfn-embedded-metadata" class="internalDFN"> insert: <a href="#dfn-embedding-metadata" class="internalDFN" data-link-type="dfn"> embedded metadata looking like:

Example 23 : Embedded metadata in the format of the annotated tabular model
  {     "@context"   :     "http://www.w3.org/ns/csvw"   ,     "url"   :     "tree-ops.csv"   ,     "dc:publisher"   :     "City of Palo Alto"   ,     "dc:updated"   :     "12/31/2010"   ,     "tableSchema"   :     {     "columns"   :     [{     "name"   :     "GID"   ,     "titles"   :     "GID"   ,     "datatype"   :     "string"   ,     },     {     "name"   :     "on_street"   ,     "titles"   :     "On Street"   ,     "datatype"   :     "string"     },     {     "name"   :     "species"   ,     "titles"   :     "Species"   ,     "datatype"   :     "string"     },     {     "name"   :     "trim_cycle"   ,     "titles"   :     "Trim Cycle"   ,     "datatype"   :     "string"     },     {     "name"   :     "inventory_date"   ,     "titles"   :     "Inventory Date"   ,     "datatype"   :     {     "base"   :     "date"   ,     "format"   :     "M/d/yyyy"     }     }]     }     }  

As before, the result would be a single delete: <a href="#dfn-table" class="internalDFN"> insert: <a href="#dfn-table" class="internalDFN" data-link-type="dfn"> table T with five columns and two rows. The table itself would have two annotations:

dc:publisher
{"@value": "City of Palo Alto"}
dc:updated
{"@value": "12/31/2010"}

The columns have the annotations shown in the following table:

id core annotations
table number source number cells name titles
C1 T 1 2 C1.1 , C2.1 GID GID
C2 T 2 3 C1.2 , C2.2 on_street On Street
C3 T 3 4 C1.3 , C2.3 species Species
C4 T 4 5 C1.4 , C2.4 trim_cycle Trim Cycle
C5 T 5 6 C1.5 , C2.5 inventory_date Inventory Date

The rows have the annotations shown in the following table, exactly as in previous examples:

id core annotations
table number source number cells
R1 T 1 6 C1.1 , C1.2 , C1.3 , C1.4 , C1.5
R2 T 2 7 C2.1 , C2.2 , C2.3 , C2.4 , C2.5

The cells have the annotations shown in the following table. Because of the way the particular tabular data format has been specified, these include additional annotations but also, for the Inventory Date column (cells C1.5 and C2.5 ), have a delete: <a title="cell value" href="#dfn-cell-value" class="internalDFN"> insert: <a data-lt="cell value" href="#dfn-value" class="internalDFN" data-link-type="dfn"> value that is a parsed date rather than an unparsed string.

id core annotations
table column row string value value
C1.1 T C1 R1 "1" "1"
C1.2 T C2 R1 "ADDISON AV" "ADDISON AV"
C1.3 T C3 R1 "Celtis australis" "Celtis australis"
C1.4 T C4 R1 "Large Tree Routine Prune" "Large Tree Routine Prune"
C1.5 T C5 R1 "10/18/2010" 2010-10-18
C2.1 T C1 R2 "2" "2"
C2.2 T C2 R2 "EMERSON ST" "EMERSON ST"
C2.3 T C3 R2 "Liquidambar styraciflua" "Liquidambar styraciflua"
C2.4 T C4 R2 "Large Tree Routine Prune" "Large Tree Routine Prune"
C2.5 T C5 R2 "6/2/2010" 2010-06-02

8.2.4 Parsing Multiple Header Lines

The following example shows a CSV file with multiple header lines:

Example 24 : CSV file with multiple header lines
  Who   ,   What   ,,   Where   ,     Organization   ,   Sector   ,   Subsector   ,   Department   ,   Municipality     #org,#sector,#subsector,#adm1,#adm2   UNICEF   ,   Education   ,   Teacher   training   ,   Choc   ó,   Quidb   ó   UNICEF   ,   Education   ,   Teacher   training   ,   Choc   ó,   Bojay   á  

Here, the first line contains some grouping titles in the first line, which are not particularly helpful. The lines following those contain useful titles for the columns. Thus the appropriate configuration for a dialect description is:

Example 25 : Dialect description for multiple header lines
  {     "skipRows"   :     1   ,     "headerRowCount"   :     2     }  

With this configuration, the table model contains five columns, each of which have two titles, summarized in the following table:

id core annotations
table number source number cells titles
C1 T 1 1 C1.1 , C2.1 Organization , #org
C2 T 2 2 C1.2 , C2.2 Sector , #sector
C3 T 3 3 C1.3 , C2.3 Subsector , #subsector
C4 T 4 4 C1.4 , C2.4 Department , #adm1
C5 T 5 5 C1.5 , C2.5 Municipality , #adm2

As metadata, this would look like:

Example 26 : Extracted metadata
  {     "tableSchema"   :     {     "columns"   :     [     {     "titles"   :     [   "Organization"   ,     "#org"   ]     },     {     "titles"   :     [   "Sector"   ,     "#sector"   ]     },     {     "titles"   :     [   "Subsector"   ,     "#subsector"   ]     },     {     "titles"   :     [   "Department"   ,     "#adm1"   ]     },     {     "titles"   :     [   "Municipality"   ,     "#adm2"   ]     },     ]     }     }  

A separate metadata file could contain just the second of each of these titles, for example:

Example 27 : Metadata file
  {     "tableSchema"   :     {     "columns"   :     [     {     "name"   :     "org"   ,     "titles"   :     #org" },     {     "name"   :     "sector"   ,     "titles"   :     #sector" },     {     "name"   :     "subsector"   ,     "titles"   :     #subsector" },     {     "name"   :     "adm1"   ,     "titles"   :     #adm1" },     {     "name"   :     "adm2"   ,     "titles"   :     #adm2" },     ]     }     }  

This enables people from multiple jurisdictions to use the same tabular data structures without having to use exactly the same titles within their documents.

A. IANA Considerations

delete: <p> This section has delete: <strong> not yet been submitted insert: <strong style="font-size:120%"> /.well-known/csvm to IANA for review, approval, and registration. delete: </p> delete: <h2 id="x.well-known-csvm"> /.well-known/csvm delete: </h2>
URI suffix:
csvm
Change controller:
W3C
Specification document(s):
This document, delete: <a href="#site-wide-location-configuration" class="sectionRef sec-ref"> insert: <a href="#default-locations-and-site-wide-location-configuration" class="sectionRef sec-ref"> section 5.3 Default Locations and Site-wide Location Configuration

B. Existing Standards

This section is non-normative.

This appendix outlines various ways in which CSV is defined.

B.1 RFC 4180

[ RFC4180 ] defines CSV with the following ABNF grammar:

 file = [header CRLF] record *(CRLF record) [CRLF] header = name *(COMMA name) record = field *(COMMA field) name = field field = (escaped / non-escaped) escaped = DQUOTE *(TEXTDATA / COMMA / CR / LF / 2DQUOTE) DQUOTE non-escaped = *TEXTDATA COMMA = %x2C CR = %x0D DQUOTE = %x22 LF = %x0A CRLF = CR LF TEXTDATA = %x20-21 / %x23-2B / %x2D-7E 

Of particular note here are:

B.2 Excel

Excel is a common tool for both creating and reading CSV documents, and therefore the CSV that it produces is a de facto standard.

delete: <div class="note-title" aria-level="4" role="heading" id="h-note22"> insert: <div class="note-title" aria-level="4" role="heading" id="h-note25">
Note

The following describes the behavior of Microsoft Excel for Mac 2011 with an English locale. Further testing is needed to see the behavior of Excel in other situations.

B.2.1 Saved CSV

Excel generates CSV files encoded using Windows-1252 with LF line endings. Characters that cannot be represented within Windows-1252 are replaced by underscores. Only those cells that need escaping (e.g. because they contain commas or double quotes) are escaped, and double quotes are escaped with two double quotes.

Dates and numbers are formatted as displayed, which means that formatting can lead to information being lost or becoming inconsistent.

B.2.2 Opened CSV

When opening CSV files, Excel interprets CSV files saved in UTF-8 as being encoded as Windows-1252 (whether or not a BOM is present). It correctly deals with double quoted cells, except that it converts line breaks within cells into spaces. It understands CRLF as a line break. It detects dates (formatted as YYYY-MM-DD ) and formats them in the default date formatting for files.

B.2.3 Imported CSV

Excel provides more control when importing CSV files into Excel. However, it does not properly understand UTF-8 (with or without BOM ). It does however properly understand UTF-16 and can read non-ASCII characters from a UTF-16-encoded file.

A particular quirk in the importing of CSV is that if a cell contains a line break, the final double quote that escapes the cell will be included within it.

B.2.4 Copied Tabular Data

When tabular data is copied from Excel, it is copied in a tab-delimited format, with LF line breaks.

B.3 Google Spreadsheets

B.3.1 Downloading CSV

Downloaded CSV files are encoded in UTF-8, without a BOM , and with LF line endings. Dates and numbers are formatted as they appear within the spreadsheet.

B.3.2 Importing CSV

CSV files can be imported as UTF-8 (with or without BOM ). CRLF line endings are correctly recognized. Dates are reformatted to the default date format on load.

B.4 CSV Files in a Tabular Data Package

Tabular Data Packages place the following restrictions on CSV files:

As a starting point, CSV files included in a Tabular Data Package package must conform to the RFC for CSV (4180 - Common Format and MIME Type for Comma-Separated Values (CSV) Files). In addition:

  • File names MUST end with .csv .

  • Files MUST be encoded as UTF-8.

  • Files MUST have a single header row. This row MUST be the first row in the file.

    • Terminology: each column in the CSV file is termed a field and its name is the string in that column in the header row.

    • The name MUST be unique amongst fields, MUST contain at least one character, and MUST conform to the character restrictions defined for the delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#column-name" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#column-name" class="externalDFN"> name property.

  • Rows in the file MUST NOT contain more fields than are in the header row (though they may contain less).

  • Each file MUST have an entry in the tables array in the datapackage.json file.

  • The resource metadata MUST include a tableSchema attribute whose value MUST be a valid delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dfn-schema-description" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dfn-schema-description" class="externalDFN"> schema description .

  • All fields in the CSV files MUST be described in the delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/#dfn-schema-description" class="externalDFN"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/#dfn-schema-description" class="externalDFN"> schema description .

CSV files generated by different applications often vary in their syntax, e.g. use of quoting characters, delimiters, etc. To encourage conformance, CSV files in a CSV files in a Tabular Data Package SHOULD :

  • Use "," as field delimiters.
  • Use CRLF ( U+000D U+000A ) or LF ( U+000A ) as line terminators.

If a CSV file does not follow these rules then its specific CSV dialect MUST be documented. The resource hash for the resource in the datapackage.json descriptor MUST :

Applications processing the CSV file SHOULD read use the dialect of the CSV file to guide parsing.

delete: <div class="note-title" aria-level="3" role="heading" id="h-note23"> insert: <div class="note-title" aria-level="3" role="heading" id="h-note26">
Note

To replicate the findings above, test files which include non-ASCII characters, double quotes, and line breaks within cells are:

C. Acknowledgements

This section is non-normative.

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.

D. Changes from previous drafts

insert: <section id="changes-since-the-candidate-recommendation-of-16-july-2015" typeof="bibo:Chapter" resource="#changes-since-the-candidate-recommendation-of-16-july-2015" property="bibo:hasPart">
insert: <h3 id="h-changes-since-the-candidate-recommendation-of-16-july-2015" resource="#h-changes-since-the-candidate-recommendation-of-16-july-2015">

insert: <span property="xhv:role" resource="xhv:heading"> insert: <span class="secno"> D.1 insert: </span> Changes since the candidate recommendation of 16 July 2015 insert: </span> insert: </h3>

insert: <ul> insert: </section>

D.1 D.2 Changes since the working draft of 16 April 2015

D.2 D.3 Changes since the working draft of 08 January 2015

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

E. References

E.1 Normative references

[BCP47]
A. Phillips; M. Davis. Tags for Identifying Languages . September 2009. IETF Best Current Practice. URL: https://tools.ietf.org/html/bcp47
[BIDI]
Mark Davis; Aharon Lanin; Andrew Glass. Unicode Bidirectional Algorithm . 5 June 2014. Unicode Standard Annex #9. URL: http://www.unicode.org/reports/tr9/
[ECMASCRIPT]
Allen Wirfs-Brock. delete: <a href="http://www.ecma-international.org/ecma-262/6.0/" property="dc:requires"> insert: <a href="https://tc39.github.io/ecma262/" property="dc:requires"> ECMA-262 6th Edition, The ECMAScript 2015 Language Specification . June 2015. Standard. URL: delete: <a href="http://www.ecma-international.org/ecma-262/6.0/" property="dc:requires"> http://www.ecma-international.org/ecma-262/6.0/ insert: <a href="https://tc39.github.io/ecma262/" property="dc:requires"> https://tc39.github.io/ecma262/
[ISO8601]
Representation of dates and times. International Organization for Standardization. 2004. ISO 8601:2004. URL: http://www.iso.org/iso/catalogue_detail?csnumber=40874
[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/
[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
[RFC3968]
G. Camarillo. The Internet Assigned Number Authority (IANA) Header Field Parameter Registry for the Session Initiation Protocol (SIP) . December 2004. Best Current Practice. URL: https://tools.ietf.org/html/rfc3968
[RFC4180]
Y. Shafranovich. Common Format and MIME Type for Comma-Separated Values (CSV) Files . October 2005. Informational. URL: https://tools.ietf.org/html/rfc4180
[RFC5785]
M. Nottingham; E. Hammer-Lahav. Defining Well-Known Uniform Resource Identifiers (URIs) . April 2010. Proposed Standard. URL: https://tools.ietf.org/html/rfc5785
[UAX35]
Mark Davis; CLDR committee members. Unicode Locale Data Markup Language (LDML) . 15 March 2013. Unicode Standard Annex #35. URL: http://www.unicode.org/reports/tr35/tr35-31/tr35.html
[UNICODE]
The Unicode Standard . URL: http://www.unicode.org/versions/latest/
[URI-TEMPLATE]
J. Gregorio; R. Fielding; M. Hadley; M. Nottingham; D. Orchard. URI Template . March 2012. Proposed Standard. URL: https://tools.ietf.org/html/rfc6570
[tabular-metadata]
Jeni Tennison; Gregg Kellogg. delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/" property="dc:requires"> insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/" property="dc:requires"> Metadata Vocabulary for Tabular Data . W3C Working Draft. Proposed Recommendation. URL: delete: <a href="http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/" property="dc:requires"> http://www.w3.org/TR/2015/CR-tabular-metadata-20150716/ insert: <a href="http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/" property="dc:requires"> http://www.w3.org/TR/2015/PR-tabular-metadata-20151117/
[xmlschema11-2]
David Peterson; Sandy Gao; Ashok Malhotra; Michael Sperberg-McQueen; Henry Thompson; Paul V. Biron et al. W3C XML Schema Definition Language (XSD) 1.1 Part 2: Datatypes . 5 April 2012. W3C Recommendation. URL: http://www.w3.org/TR/xmlschema11-2/

E.2 Informative references

[EBNF-NOTATION]
Tim Bray; Jean Paoli; C. Michael Sperberg-McQueen; Eve Maler; François Yergau. EBNF Notation . W3C Recommendation. URL: http://www.w3.org/TR/xml/#sec-notation
[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
[annotation-model]
Robert Sanderson; Paolo Ciccarese. Ciccarese; Benjamin Young. Web Annotation Data Model . 11 December 2014. 15 October 2015. W3C Working Draft. URL: http://www.w3.org/TR/annotation-model/
[csv2json]
Jeremy Tandy; Ivan Herman. delete: <a href="http://www.w3.org/TR/2015/CR-csv2json-20150716/" property="dc:references"> insert: <a href="http://www.w3.org/TR/2015/PR-csv2json-20151117/" property="dc:references"> Generating JSON from Tabular Data on the Web . W3C Working Draft. Proposed Recommendation. URL: delete: <a href="http://www.w3.org/TR/2015/CR-csv2json-20150716/" property="dc:references"> http://www.w3.org/TR/2015/CR-csv2json-20150716/ insert: <a href="http://www.w3.org/TR/2015/PR-csv2json-20151117/" property="dc:references"> http://www.w3.org/TR/2015/PR-csv2json-20151117/
[csv2rdf]
Jeremy Tandy; Ivan Herman; Gregg Kellogg. delete: <a href="http://www.w3.org/TR/2015/CR-csv2rdf-20150716/" property="dc:references"> insert: <a href="http://www.w3.org/TR/2015/PR-csv2rdf-20151117/" property="dc:references"> Generating RDF from Tabular Data on the Web . W3C Working Draft. Proposed Recommendation. URL: delete: <a href="http://www.w3.org/TR/2015/CR-csv2rdf-20150716/" property="dc:references"> http://www.w3.org/TR/2015/CR-csv2rdf-20150716/ insert: <a href="http://www.w3.org/TR/2015/PR-csv2rdf-20151117/" property="dc:references"> http://www.w3.org/TR/2015/PR-csv2rdf-20151117/
[encoding]
Anne van Kesteren; Joshua Bell; Addison Phillips. Encoding . 16 September 2014. 20 October 2015. W3C Candidate Recommendation. URL: http://www.w3.org/TR/encoding/
insert: <dt id="bib-vocab-data-cube">
[vocab-data-cube] insert: </dt>
insert: <dd>
Richard Cyganiak; Dave Reynolds. insert: <a href="http://www.w3.org/TR/vocab-data-cube/" property="dc:references"> insert: <cite> The RDF Data Cube Vocabulary insert: </cite> insert: </a> . 16 January 2014. W3C Recommendation. URL: insert: <a href="http://www.w3.org/TR/vocab-data-cube/" property="dc:references"> http://www.w3.org/TR/vocab-data-cube/ insert: </a> insert: </dd>