Drag-and-drop schema mapping for the analyst. Code-first expressions for the engineer. Both views stay in sync, and every functoid you wired in BizTalk has a one-line equivalent here - usually one that does more, in fewer pieces.
Source on the left, destination on the right, lines between them. Schema constraints validated as you draw.
Drop into code when the transformation needs it. Round-trips back to the visual view automatically.
Validate inbound and outbound shapes. Reject bad messages at the boundary, not three pipelines deep.
Publish a tested map once, version it, import it across pipelines. No more copy-paste mapping drift.
If you spent the 2010s wiring Functoids in BTM, here’s the translation. Pick a common transformation - the legacy graph is on the left, the Art2link expression on the right.
Loops over a repeating element and adds the values into a single output. BTM graph: a Cumulative Sum functoid wired to a looping input.
Aggregate expressions are first-class. The mapper validates type compatibility at design time, not runtime.
// Sum line-item totals into invoice total invoice.total = sum(invoice.lineItems[*].amount)
Joins 2+ string inputs into one output, with an optional separator. Each separator becomes another connection in the BTM graph.
Template strings, null-safe operators, and trim are built in. No more 14-functoid contraption to assemble a person's name.
// Build full name from PID-5 components
out.fullName = `${pid.given} ${pid.middle ?? ''} ${pid.family}`.trim()
Several functoids combined: parse, add days, then format to a new string. Often 3-4 wired functoids per date column.
Native date math, timezone-aware, ISO 8601 in and out. Same expression handles both batch and streaming pipelines.
// HL7 v2 YYYYMMDD → ISO 8601
out.dob = parseDate(pid.dob, 'YYYYMMDD').toISO()
// Add 30 days for due date
out.due = parseDate(invoice.date, 'YYYY-MM-DD').plus({ days: 30 }).toISO()
Branch on a condition (Equal), choose between values (Value Mapping), and copy a subtree when a sibling exists (Mass Copy). Three functoids wired.
Plain conditionals. The mapper still renders this as a visual flow for non-coders — both views stay in sync.
// Map insurance type only when present
if (claim.payer && claim.payer.type === 'medicare') {
out.coverage = 'medicare-primary'
} else {
out.coverage = 'commercial'
}
// Mass-copy the address block when home address exists
if (pid.address.home) out.shipTo = pid.address.home
Send us your BizTalk Map (.btm). We’ll return the Art2link transform alongside, so you can see the migration shape for a real map of yours - not a marketing one.