Merge several files into one output

Combine data from several files, even in different formats, into a single report: exchange rates from an XML feed plus orders from a JSON export, for example.

1. List the input files

A small YAML file names every input and the label it gets in the template:

- file: rates.xml     # path, relative to the current directory
  label: RATES        # the data is available as {{ .RATES }}
- file: orders.json
  label: ORDERS       # format omitted: taken from the .json extension
  # format: json      # set it when the extension is missing or unusual

Pass it with a ? in front of the name, in quotes: -i '?files.yaml'. Without quotes, zsh (the macOS default shell) treats ? as a wildcard and stops with no matches found.

2. The input files

<rates date="2024-03-01">
  <rate currency="USD">1.0812</rate>
  <rate currency="CZK">25.304</rate>
</rates>
[
  {"id": 1, "amount": 100, "currency": "USD"},
  {"id": 2, "amount": 2530, "currency": "CZK"}
]

3. Template

Labels are the top-level keys. $ always refers to the root, which is handy inside range.

Orders in EUR (rates of {{index .RATES.rates "-date"}})
{{- range .ORDERS}}
{{- $order := .}}
{{- range $.RATES.rates.rate}}
{{- if eq (index . "-currency") $order.currency}}
#{{$order.id}}: {{$order.amount}} {{$order.currency}} = {{round (divf $order.amount (index . "#text")) 2}} EUR
{{- end}}
{{- end}}
{{- end}}
bafi -i '?files.yaml' -t summary.tmpl
Orders in EUR (rates of 2024-03-01)
#1: 100 USD = 92.49 EUR
#2: 2530 CZK = 99.98 EUR

In PowerShell and cmd.exe use double quotes: -i "?files.yaml".

Each file is parsed on its own, so a broken file is reported with its own name and line. The -d delimiter applies to every CSV file in the list.

Related: HTML report from JSON ยท Command line