n8n-nodes-data-mapper 0.4.0 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,14 +6,15 @@
6
6
 
7
7
  An [n8n](https://n8n.io) community node that **maps whatever comes in onto a target structure** and outputs **XML, JSON or CSV**.
8
8
 
9
- Paste a **target profile** (an XML/JSON/Flat File profile component, JSON Schema, sample JSON or XML, XSD, or a CSV header) and its fields appear as a target list. Then **drag fields from n8n's Input panel onto the target fields**, the same way you draw lines in a visual mapper, or let **Map Automatically** match them by name. You don't need a source profile: anything the previous node outputs can be mapped.
9
+ Add a mapping for each field: pick the **source** (an input path, a field from a source profile, or a fixed value/expression) and the **target** (a path you type, or a field from a target profile), with built-in **transforms** along the way. Or let **Auto-Map** match source fields to a target profile by name. Paste a profile — an XML/JSON/Flat File profile component, JSON Schema, sample JSON or XML, XSD, or a CSV header — and its fields become selectable dropdowns on both sides.
10
+
11
+ There is also a **visual drag-and-drop mapper** (node version 2); see [below](#visual-drag-and-drop-mapper-node-version-2).
10
12
 
11
13
  Use it to turn an API response into a partner's XML order, shape database rows into a CSV export, read a supplier's XML into clean JSON, or pull the useful parts out of a large payload.
12
14
 
13
15
  - [Screenshots](#screenshots)
14
16
  - [Installation](#installation)
15
- - [Drag-and-drop mapping](#drag-and-drop-mapping)
16
- - [Classic mode quick start](#classic-mode-quick-start)
17
+ - [Quick start](#quick-start)
17
18
  - [Paths](#paths)
18
19
  - [Parameters](#parameters)
19
20
  - [Transforms](#transforms)
@@ -21,6 +22,7 @@ Use it to turn an API response into a partner's XML order, shape database rows i
21
22
  - [Reusable JSON definitions](#reusable-json-definitions)
22
23
  - [Working with XML](#working-with-xml)
23
24
  - [Examples](#examples)
25
+ - [Visual drag-and-drop mapper (node version 2)](#visual-drag-and-drop-mapper-node-version-2)
24
26
  - [Security](#security)
25
27
  - [Compatibility](#compatibility)
26
28
  - [Development](#development)
@@ -32,6 +34,8 @@ Use it to turn an API response into a partner's XML order, shape database rows i
32
34
 
33
35
  ![Data Mapper producing JSON output](docs/images/json-mapping.webp)
34
36
 
37
+ <img width="2340" height="1362" alt="image" src="https://github.com/user-attachments/assets/81a3540f-9aee-40b7-8510-c8a2cbe39bcb" />
38
+
35
39
  **Building XML with transforms and added fields** — attributes, nested elements, repeated items, a country lookup, rounding and a generated timestamp:
36
40
 
37
41
  ![Data Mapper producing XML output](docs/images/xml-output.webp)
@@ -57,80 +61,9 @@ tar -xzf n8n-nodes-data-mapper-*.tgz && mv package n8n-nodes-data-mapper
57
61
 
58
62
  Restart n8n afterwards.
59
63
 
60
- ## Drag-and-drop mapping
61
-
62
- New Data Mapper nodes (node version 2) work like a visual mapper:
63
-
64
- ```
65
- INPUT panel (whatever comes in) Data Mapper (target profile)
66
- ─────────────────────────────── ──────────────────────────────
67
- OrderID "A1" ──drag──▶ order › @id
68
- Currency "eur" ──drag──▶ order › currency
69
- Items[0].SKU "P-1" ──drag──▶ order › line[] › sku
70
- Items[0].Qty "2" ──drag──▶ order › line[] › quantity (number)
71
- ```
72
-
73
- 1. **Output Format** — pick **XML**, **JSON** or **CSV**.
74
- 2. **Source Data** — *Incoming Item* (default), or *XML or JSON Text in a Field* / *XML or JSON File* when the order arrives as raw text, e.g. in a `data` field.
75
- 3. **Source Profile** (optional) — paste the structure of the incoming data, such as a sample order. Every target field then gets a **dropdown of source fields**, like picking the source side of a line in a visual mapper. You can still switch any field to an expression.
76
- 4. **Target Profile** — paste the profile. Its fields load into **Target Fields** as a tree (`order › line[] › @sku`): `›` separates levels, `[]` marks a repeating element, `@` an XML attribute, `(number)` a type and `*` a required field.
77
- 5. **Target Fields** — for each target field, pick the source field from the dropdown (with a Source Profile), or drag a field from the **Input** panel and drop it into the box. Or set the mode to **Map Automatically** and the node matches source fields to target fields by similar names (`OrderID` → `orderId`, `Qty` → `quantity`).
78
- 6. Run the node.
79
-
80
- A source profile made from a one-item sample still maps every item of a real order: when a picked field sits inside a list in the actual data (`orders.order.lines.line.sku` with several `line`s), each element becomes its own target element.
81
-
82
- What a drop can be:
83
-
84
- | You put in a target box | What happens |
85
- | --- | --- |
86
- | A field picked from the Source Profile dropdown | That field is copied across (lists included). |
87
- | A dragged field, `{{ $json.OrderID }}` | That field is copied across. |
88
- | A dragged field from a list, `{{ $json.Items[0].SKU }}`, on a repeating target (`line[]`) | Every element is mapped, not just the first: one `line` per item. |
89
- | A dragged single field on a repeating target, e.g. `{{ $json.Currency }}` → `line[] › currency` | The value is written into every line. |
90
- | Any expression, e.g. `{{ $json.Currency.toUpperCase() }}` or `{{ $now.toISO() }}` | Its result is used. Expressions work like map functions: `.trim()`, `.toUpperCase()`, `.toNumber()`, `.toDateTime().toFormat('dd/MM/yyyy')`, a lookup object `{{ ({ NL: 'Netherlands' })[$json.Country] }}`, and so on. |
91
- | An expression returning a list on a repeating target, e.g. `{{ $json.Items.map(i => i.SKU) }}` | Element `n` of the list goes to element `n` of the target. |
92
- | Fixed text, e.g. `n8n` | Written as-is. |
93
- | Nothing | The target field is left out (turn on **Keep Empty Values** to write it empty). |
94
-
95
- The output always follows the **order of the target profile**, which matters to XML consumers and XSD validation. Numbers and booleans are converted where the profile says so (**Convert Types From Profile**); a value that can't be converted is kept as it is instead of failing the run.
96
-
97
- ### Output
98
-
99
- | Output Format | Output To: Item | Output To: File |
100
- | --- | --- | --- |
101
- | JSON | The mapped data becomes the item | `output.json` |
102
- | XML | XML text in the `xml` field | `output.xml` |
103
- | CSV | CSV text in the `csv` field | `output.csv` |
104
-
105
- CSV columns follow the profile. By default every incoming item becomes rows in **one CSV**, with a header row. A repeating target (`lines[]`) gives one row per element, with the other columns repeated.
106
-
107
- ### Options
108
-
109
- | Option | Default | Description |
110
- | --- | --- | --- |
111
- | Add Auto-Map Report | off | Adds `_autoMap` with matched and unmatched fields (Map Automatically, JSON output). |
112
- | Auto-Map Minimum Confidence | 0.6 | How close names must be, 0 to 1. |
113
- | Convert Types From Profile | on | Turn values into numbers/booleans where the profile says so. |
114
- | CSV Delimiter / Header Row / Line Ending | `,` / on / LF | CSV formatting. |
115
- | Escape CSV Formulas | off | Put `'` in front of values starting with `=`, `+`, `-`, `@`, tab or CR, so spreadsheets don't run them as formulas (CSV injection). |
116
- | Include XML Declaration | on | Start XML with `<?xml version="1.0" encoding="UTF-8"?>`. |
117
- | Keep Empty Values | off | Write empty target fields instead of leaving them out. |
118
- | One CSV for All Items | on | One CSV for the whole run, or one per item. |
119
- | Profile Format / Source Profile Format | Detect Automatically | Force a profile type if detection guesses wrong. |
120
- | Read Profile From Binary Field | | Read the profile from an uploaded file at run time (works with Map Automatically; to drag and drop, paste the profile). |
121
- | Root Element | | XML root name. Defaults to the root of a sample-XML target profile. |
122
-
123
- ### Tips
124
-
125
- - **CSV, Excel or other files coming in?** Put an **Extract from File** node first so each row becomes an item you can drag from.
126
- - **Input is raw XML in a field and you can't drag from it?** Set **Source Data** to *XML or JSON Text in a Field* and paste a **Source Profile**: you then pick source fields from dropdowns.
127
- - **The field list is empty?** It loads from the pasted profile. If the profile comes from an expression, n8n can't list its fields at design time: paste it, or use Map Automatically.
128
- - **Changed the profile?** Use the refresh button above the target fields to reload them.
129
- - Existing workflows keep the **classic mode** (node version 1) described below. Nothing changes for them.
130
-
131
- ## Classic mode quick start
64
+ ## Quick start
132
65
 
133
- Data Mapper nodes created before version 0.3.0 (node version 1) use path-based mappings with built-in transforms. Given this input item:
66
+ Given this input item:
134
67
 
135
68
  ```json
136
69
  {
@@ -195,13 +128,16 @@ Mappings run in order, and a later mapping to the same target overwrites an earl
195
128
  | **Input** | *Item JSON* maps each incoming item. *Text Field* first parses JSON or XML text stored in a field. *File* first parses a JSON or XML binary file. |
196
129
  | **Input Field** / **Input Binary Field** | Which field holds the text or file. |
197
130
  | **Input Format** | *Detect Automatically* (XML when the text starts with `<`), *JSON* or *XML*. |
198
- | **Define Mappings** | *Using Fields Below*, *Auto-Map From Profile*, or *Using JSON*. See [Target profiles and auto-map](#target-profiles-and-auto-map) and [Reusable JSON definitions](#reusable-json-definitions). |
131
+ | **Define Mappings** | *Map Each Column Manually*, *Auto-Map From Profile*, or *Using JSON*. See [Target profiles and auto-map](#target-profiles-and-auto-map) and [Reusable JSON definitions](#reusable-json-definitions). |
199
132
  | **Target Profile** / **Target Profile Format** | Optional. The structure to map into. See [Target profiles and auto-map](#target-profiles-and-auto-map). |
200
- | **Source Profile** / **Source Profile Format** | Optional (*Using Fields Below*). The structure of the incoming data, so each mapping can use **Source: From Source Profile** and pick the field from a dropdown. |
133
+ | **Source Profile** / **Source Profile Format** | Optional (*Map Each Column Manually*). The structure of the incoming data, so each mapping can use **Source: From Source Profile** and pick the field from a dropdown. |
201
134
  | **Mappings** | The list of mappings. Each has a **Source** (*Input Field* path, *From Source Profile* dropdown, or *Fixed Value*, which can be an expression), a **Target** (*Custom Path* you type, or *From Target Profile* picked from a dropdown), an optional **Transform**, and **If Source Is Missing**: *Leave Out* (default), *Set to Null*, *Use Default* or *Stop With Error*. |
202
- | **Auto-Map Remaining Target Fields** | *Fields mode.* Fills any profile fields you did not map by hand by matching them to source fields by name. |
135
+ | **Transform a Field** | *Fill Target Fields.* Pick a target field and apply a transform (trim, number, date, lookup, split/join, ...). Shown as a list under the fields. |
136
+ | **CSV Options** | *CSV / CSV File output.* Delimiter, header row, line ending, one CSV for all items, and formula escaping. |
137
+ | **Mapping Layout** | *Map Each Column Manually.* *One Mapping at a Time* (row-by-row list) or *Fill Target Fields* — lists every target-profile field and you set the source for each (from the Source Profile dropdown, a drag, or an expression). |
138
+ | **Auto-Map Remaining Target Fields** | *One Mapping at a Time.* Fills any profile fields you did not map by hand by matching them by name. Tuned by **Auto-Map Options** (confidence, synonyms, report, ...). |
203
139
  | **Unmapped Fields** | *Drop* outputs only mapped fields. *Keep* starts from a copy of the input and applies the mappings on top. |
204
- | **Output Format** | *JSON* (the item), *JSON File*, *XML* (text in a field) or *XML File*. |
140
+ | **Output Format** | *JSON* (the item), *JSON File*, *XML* (text in a field), *XML File*, *CSV* (text in a field) or *CSV File*. |
205
141
  | **Put Output in Field** | *XML only.* Default `xml`. |
206
142
  | **Put Output File in Field** / **File Name** | *File outputs only.* Defaults `data` and `output.xml` / `output.json`. |
207
143
  | **Root Element** | *XML outputs only.* Leave empty to use the single top-level field as the root, or `root` when there are several. |
@@ -253,7 +189,7 @@ A **target profile** describes the structure you want to map into. Paste it into
253
189
 
254
190
  ### Picking targets (manual mode)
255
191
 
256
- With **Define Mappings** = *Using Fields Below*, paste a profile, then set a mapping's **Target** to *From Target Profile* and choose the field from the dropdown. The dropdown shows each field's path, whether it is a list, and its type. Switch **Target** to *Custom Path* to type a path the profile does not contain.
192
+ With **Define Mappings** = *Map Each Column Manually*, paste a profile, then set a mapping's **Target** to *From Target Profile* and choose the field from the dropdown. The dropdown shows each field's path, whether it is a list, and its type. Switch **Target** to *Custom Path* to type a path the profile does not contain.
257
193
 
258
194
  ### Auto-map
259
195
 
@@ -270,7 +206,7 @@ With **Define Mappings** = *Auto-Map From Profile*, the node matches each target
270
206
  | Unmatched Target Fields | Leave Out | *Leave Out*, or *Set to Null* to include them as null. |
271
207
  | Add Auto-Map Report | off | Adds an `_autoMap` field listing matched and unmatched fields (JSON output). |
272
208
 
273
- Auto-map respects arrays: `items[*].Qty` → `lines[*].qty` works, and a non-repeating source is never mapped onto a repeating target. To tweak a few fields by hand, use *Using Fields Below* with **Auto-Map Remaining Target Fields** on — your manual mappings win, and the rest are filled in automatically.
209
+ Auto-map respects arrays: `items[*].Qty` → `lines[*].qty` works, and a non-repeating source is never mapped onto a repeating target. To tweak a few fields by hand, use *Map Each Column Manually* with **Auto-Map Remaining Target Fields** on — your manual mappings win, and the rest are filled in automatically.
274
210
 
275
211
  For an XML target profile, the root element name comes from the profile, so XML output needs no **Root Element**.
276
212
 
@@ -412,6 +348,78 @@ Keep three fields from a big payload: **Unmapped Fields** *Drop*, with mappings
412
348
 
413
349
  Put one Data Mapper on each source branch, each mapping into the same target shape, then merge the branches.
414
350
 
351
+ ## Visual drag-and-drop mapper (node version 2)
352
+
353
+ > **Not the default.** New Data Mapper nodes use the classic field mappings above. The visual mapper is **node version 2**, kept so nodes already built with it keep working. It turns the node into a drag-and-drop mapper:
354
+
355
+ ```
356
+ INPUT panel (whatever comes in) Data Mapper (target profile)
357
+ ─────────────────────────────── ──────────────────────────────
358
+ OrderID "A1" ──drag──▶ order › @id
359
+ Currency "eur" ──drag──▶ order › currency
360
+ Items[0].SKU "P-1" ──drag──▶ order › line[] › sku
361
+ Items[0].Qty "2" ──drag──▶ order › line[] › quantity (number)
362
+ ```
363
+
364
+ 1. **Output Format** — pick **XML**, **JSON** or **CSV**.
365
+ 2. **Source Data** — *Incoming Item* (default), or *XML or JSON Text in a Field* / *XML or JSON File* when the order arrives as raw text, e.g. in a `data` field.
366
+ 3. **Source Profile** (optional) — paste the structure of the incoming data, such as a sample order. Every target field then gets a **dropdown of source fields**, like picking the source side of a line in a visual mapper. You can still switch any field to an expression.
367
+ 4. **Target Profile** — paste the profile. Its fields load into **Target Fields** as a tree (`order › line[] › @sku`): `›` separates levels, `[]` marks a repeating element, `@` an XML attribute, `(number)` a type and `*` a required field.
368
+ 5. **Target Fields** — for each target field, pick the source field from the dropdown (with a Source Profile), or drag a field from the **Input** panel and drop it into the box. Or set the mode to **Map Automatically** and the node matches source fields to target fields by similar names (`OrderID` → `orderId`, `Qty` → `quantity`).
369
+ 6. Run the node.
370
+
371
+ A source profile made from a one-item sample still maps every item of a real order: when a picked field sits inside a list in the actual data (`orders.order.lines.line.sku` with several `line`s), each element becomes its own target element.
372
+
373
+ What a drop can be:
374
+
375
+ | You put in a target box | What happens |
376
+ | --- | --- |
377
+ | A field picked from the Source Profile dropdown | That field is copied across (lists included). |
378
+ | A dragged field, `{{ $json.OrderID }}` | That field is copied across. |
379
+ | A dragged field from a list, `{{ $json.Items[0].SKU }}`, on a repeating target (`line[]`) | Every element is mapped, not just the first: one `line` per item. |
380
+ | A dragged single field on a repeating target, e.g. `{{ $json.Currency }}` → `line[] › currency` | The value is written into every line. |
381
+ | Any expression, e.g. `{{ $json.Currency.toUpperCase() }}` or `{{ $now.toISO() }}` | Its result is used. Expressions work like map functions: `.trim()`, `.toUpperCase()`, `.toNumber()`, `.toDateTime().toFormat('dd/MM/yyyy')`, a lookup object `{{ ({ NL: 'Netherlands' })[$json.Country] }}`, and so on. |
382
+ | An expression returning a list on a repeating target, e.g. `{{ $json.Items.map(i => i.SKU) }}` | Element `n` of the list goes to element `n` of the target. |
383
+ | Fixed text, e.g. `n8n` | Written as-is. |
384
+ | Nothing | The target field is left out (turn on **Keep Empty Values** to write it empty). |
385
+
386
+ The output always follows the **order of the target profile**, which matters to XML consumers and XSD validation. Numbers and booleans are converted where the profile says so (**Convert Types From Profile**); a value that can't be converted is kept as it is instead of failing the run.
387
+
388
+ ### Output
389
+
390
+ | Output Format | Output To: Item | Output To: File |
391
+ | --- | --- | --- |
392
+ | JSON | The mapped data becomes the item | `output.json` |
393
+ | XML | XML text in the `xml` field | `output.xml` |
394
+ | CSV | CSV text in the `csv` field | `output.csv` |
395
+
396
+ CSV columns follow the profile. By default every incoming item becomes rows in **one CSV**, with a header row. A repeating target (`lines[]`) gives one row per element, with the other columns repeated.
397
+
398
+ ### Options
399
+
400
+ | Option | Default | Description |
401
+ | --- | --- | --- |
402
+ | Add Auto-Map Report | off | Adds `_autoMap` with matched and unmatched fields (Map Automatically, JSON output). |
403
+ | Auto-Map Minimum Confidence | 0.6 | How close names must be, 0 to 1. |
404
+ | Custom Synonyms | | Extra `source=target` name matches, one per line or a JSON object. |
405
+ | Convert Types From Profile | on | Turn values into numbers/booleans where the profile says so. |
406
+ | CSV Delimiter / Header Row / Line Ending | `,` / on / LF | CSV formatting. |
407
+ | Escape CSV Formulas | off | Put `'` in front of values starting with `=`, `+`, `-`, `@`, tab or CR, so spreadsheets don't run them as formulas (CSV injection). |
408
+ | Include XML Declaration | on | Start XML with `<?xml version="1.0" encoding="UTF-8"?>`. |
409
+ | Keep Empty Values | off | Write empty target fields instead of leaving them out. |
410
+ | One CSV for All Items | on | One CSV for the whole run, or one per item. |
411
+ | Profile Format / Source Profile Format | Detect Automatically | Force a profile type if detection guesses wrong. |
412
+ | Read Profile From Binary Field | | Read the profile from an uploaded file at run time (works with Map Automatically; to drag and drop, paste the profile). |
413
+ | Root Element | | XML root name. Defaults to the root of a sample-XML target profile. |
414
+
415
+ ### Tips
416
+
417
+ - **CSV, Excel or other files coming in?** Put an **Extract from File** node first so each row becomes an item you can drag from.
418
+ - **Input is raw XML in a field and you can't drag from it?** Set **Source Data** to *XML or JSON Text in a Field* and paste a **Source Profile**: you then pick source fields from dropdowns.
419
+ - **The field list is empty?** It loads from the pasted profile. If the profile comes from an expression, n8n can't list its fields at design time: paste it, or use Map Automatically.
420
+ - **Changed the profile?** Use the refresh button above the target fields to reload them.
421
+ - Existing workflows keep the **classic mode** (node version 1) described below. Nothing changes for them.
422
+
415
423
  ## Security
416
424
 
417
425
  - **No runtime dependencies.** The published package is only the compiled node; nothing else is installed into your n8n.