Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

The mapping form

The mapping form builds a mapping block for a CSV, JSON, XML or spreadsheet data file by pointing and clicking. It writes ordinary Dolfin into a .dlf file: the text is the only copy, and the form is another way to look at it. What the form saves is exactly what the formatter would print.

Opening it

  • New mapping: right-click a .csv, .json, .xml, .gpx, .xlsx, .xlsm or .ods file in the file tree and choose ⇄ New mapping from file…. Pick the .dlf file to write into at the top of the form. It defaults to the open file when that is a .dlf, else to the first .dlf of the project by name. A project with no .dlf file yet asks you to create one first.
  • Existing mapping: right-click a .dlf file. Each mapping in it is listed as ⇄ Mapping 1: Airport.csv, ⇄ Mapping 2: …. Choose one to open it. A mapping marked (text) opens in Edit as text only.
  • From the editor: right-click inside a mapping block of an open .dlf file and choose ⇄ Open in mapping editor. If you just edited the block and the change is not saved yet, a message says so: try again a moment later.

The form opens in the editor pane, under a tab such as New mapping: Airport.csv or Mapping 1: airports.dlf. Its ✕ or the form’s Close button closes it without saving.

The right-click menu, and so the form, is only offered to people who may edit the project.

The three columns

ColumnWhat you do there
SourceFor a CSV, its header and first 20 rows. Click a header to bind it to a variable, click it again to unbind. Bound headers are highlighted. A spreadsheet shows one sheet the same way: see Spreadsheet sources. A JSON or XML file is shown as a tree instead: see JSON and XML sources.
VariablesOne line per bound column or path. Rename a variable here (latitude → lat) or remove it with ×. A header (or a JSON key, an attribute or an element name) becomes a lowercased name with every character other than an ASCII letter or digit replaced by _ (Stop name → stop_name), with a _ in front of a leading digit, col for an empty header, and _2, _3… when the name is taken.
TargetThe facts each row produces. Per fact: a prefix picker and the subject template (the variable chips below it insert {?id}), the class after a, then one row per property: the property, a value (a variable picked from the list, or any constant), and a cast (int, float, boolean, date, string, or no cast). The cast is pre-filled from the property’s type when the project declares it. + add property and + add fact add rows, × removes one.

A subject or value that mentions a variable no binding defines (after a rename, say) is flagged in red under it: Unknown variable ?x.

Spreadsheet sources

An .xlsx, .xlsm or .ods file is read on the server; the form shows one of its sheets like a CSV file: the header and the first 20 rows, with headers to click. Above the table:

  • sheet lists the workbook’s worksheets in order, hidden ones included. (first worksheet) leaves the sheet line out, and the mapping reads the first worksheet. Picking a sheet writes sheet "Stops".
  • header row is the sheet row number of the header, as the spreadsheet application numbers it. Rows above it are skipped. Empty, it leaves the header row line out, and the header is the sheet’s first used row. Typing 3 writes header row 3.

Cells are shown as a deploy reads them: dates as 2024-01-01, numbers without a trailing .0, an error cell as its code (#DIV/0!). Blank rows are skipped. The language reference explains how cells become text.

Changing the sheet keeps your bindings: a header the new sheet lacks shows up as an error in the preview, as for a CSV file. A sheet that is empty shows This sheet is empty.; a missing sheet, an empty header row or a file that is not a valid workbook shows the reason under the controls.

Spreadsheets need an Agrafe server built with spreadsheet support (agrafe.dolfin.fr is). Without it they cannot be imported, and a spreadsheet mapping opens in Edit as text only.

JSON and XML sources

A .json, .xml or .gpx file is shown as a tree, and the form writes the path form of the mapping: a for each line and one path per variable.

  • for each. A node that can say what a row is carries a for each button: a JSON array (shown as [*] each of 3 items) or an XML element. Elements repeated under one parent are marked (repeated): they are the usual choice. Click for each to make that node the row, click it again to go back to one row for the whole document. The current choice is shown above the tree.
  • Binding a value. Click a leaf to bind it, click it again to unbind it. A JSON leaf is a single value (string, number, true/false, null); an XML leaf is an attribute (@id) or an element’s text (text()). Objects and elements with children are not leaves: bind the values inside them. An array of plain values is a leaf too, with a note that a binding takes its first value unless that array is the for each.
  • Paths. Each binding is written relative to the for each: with for each "$.venue[*]", the city is "$.location.city"; with for each "/transport/bus", the bus number is "@id" and its name "name/text()". A leaf outside the for each is dimmed and cannot be bound. Choosing another for each rewrites the bound paths for it; bindings that fall outside it are removed, and the form names them.
  • Order. JSON object members are listed in alphabetical order, the order the reader uses; array items keep the file’s order. The tree merges the items of an array, so a key only some items have is still listed.
  • XML namespaces. An element or attribute in a namespace is written with a prefix the .dlf file declares for that namespace, such as h:item after prefix <http://h.example/ns#> as h. Without such a line the node is shown greyed out with a hint, and nothing under it can be bound: add the prefix line to the file the mapping is written into and the tree updates. See Namespaces for how prefixes resolve.
  • Large and broken files. The tree reads the first 20 items of each array and of each repeated element, up to 400 nodes, and says so when it shows a sample. A file that is not valid JSON or XML (including an XML file with a DTD) shows the parser’s error instead of the tree; the other columns stay usable.

The language reference explains what a path matches, and the XPath subset mappings accept.

Suggestions

Once a fact has a class the project declares, the form matches the CSV headers (or, for JSON and XML, the names of the leaves under the for each) to that class’s property names (ignoring case, camelCase, snake_case, dashes and spaces, and tolerating a prefix, a missing word or a small typo, such as lat for latitude) and lists the matches under Suggested from the source, as dimmed rows under the fact’s properties. Accept binds the header or leaf if needed and adds the property row with the cast its type calls for; Accept all does it for every row; Dismiss hides one while the form stays open. Nothing is added to the mapping until you accept it. Headers and leaves a property row already reads, and properties already present, are not suggested. Only properties with a literal type (string, int, date…) are suggested: a property whose type is a concept needs an IRI, not a cell.

The MCP tool draft_mapping builds the same kind of draft for a whole CSV file.

Preview

Once a value is bound and a fact exists, Preview (first 20 rows) below the columns expands the mapping over the first 20 rows as you edit (CSV records, or matches of the for each; a spreadsheet mapping expands its whole sheet), and shows the Turtle it produces with a summary such as 3 rows → 2 facts · row 2: empty value for required binding ?id. When several rows are skipped, the summary names the first and adds (+2 more skipped); a skip is named before any warning on an earlier row, and when no row is skipped the summary names the first row with a warning instead.

A row with a bad value, such as an empty cell the subject needs or a cell a cast cannot read, is skipped whole, as a deploy would skip it. Skipped rows are shown in red in the source table, with the reason on hover, and listed under the table or the tree (row 2 is the second match of the for each). Errors that concern the whole mapping, such as a template that does not parse, are shown in the preview. The language reference explains which values skip a row.

Saving

Save writes the block into the chosen file (a new mapping is appended, an existing one is replaced in place), shows Mapping saved, refreshes the graph and closes the form. If the save is refused, the reason is shown above the columns and your draft is kept.

If the mapping you opened is no longer where it was in the file (a collaborator edited or removed it, or removed a mapping above it), saving is refused with a message asking you to reload. Click Reload: if the mapping only moved, the form follows it and you can save again. If it was edited, removed, or can no longer be shown in the form, the form closes and asks you to reopen it from the file tree.

Edit as text

Edit as text opens the .dlf file at the mapping in the Dolfin editor. Some blocks cannot be shown faithfully in the form: a comment inside the block, a sheet or header row line outside a spreadsheet mapping, a for each in a CSV or spreadsheet mapping, an is … of or a … line in a fact, a value with several entries or a nested [ … ], a where: block or a case table. Those open as a short notice with only Edit as text and Close, so saving from the form never drops anything.