Business-critical XML & JSON integration

Integrations live in days. Changes in minutes.

Payment files, shipment events, claims, patient records, product feeds, market messages: every XML and JSON flow between your systems and your partners, built from examples instead of specifications, tested automatically and promoted DEV → TEST → PROD in a click. The business gets its change the same week; IT keeps every version, every test and the way back. Less waiting, fewer incidents, no licence per message.

Streaming beats building trees

Same fields, 100 MB input
Tree capture
Whole document in memory
1.99 sbaseline
Streaming, full scan
One pass, constant memory
0.74 s~135 MB/s
Streaming, early exit
Stops when every field is found
28 µsreads only what it needs
JMH, AMD Ryzen AI 9 HX PRO 370, JVM 25 with generational ZGC. Laptop measurements; every speed claim in MerlinXSL comes with before/after numbers from the same benchmark.

In numbers

~40 µsengine work per 1 KB request
7 000requests / s, one laptop, real HTTP
100 MBsplit in a 512 MiB heap
0database calls per request

Why MerlinXSL

01
Open source, all the way down
Saxon-HE (MPL-2.0), never PE or EE. Every dependency is on an allow-list enforced by the build. No commercial tier, no licence key file, no feature that only works with one.
02
Speed is a requirement
A change that slows the runtime is a bug, even when every test is green. Stylesheets compile once at deploy; requests only run them.
03
Your documents stay home
Self-hosted, multi-tenant, per-organization data. AI is opt-in per project and can be restricted to local models only.

The platform

01Three components
Transform
XSLT 1.0, 2.0 and 3.0 stylesheets with imports, includes and lookup documents. XML → XML, JSON → XML, XML → JSON, JSON → JSON.
Extract & Detect
Capture typed fields with XPath 3.1 or JSON paths — streamed when possible. Detections answer one question: does this document apply?
02Pipelines
Ordered chains
Detect → transform → extract on one document, parsed once per format. Conditional steps are skipped when their detection does not match.
Pipeline of pipelines
Route steps send each message to the sub pipeline for its detected version — one entry point per message family, up to four levels deep, cycles refused.
03Visual mapper
Drag, click, done
Source tree from your sample, target tree from your expected output, lines in between. Live output, tests and generated XSLT below — no set-up step.
Full stylesheet editor
For what a mapper cannot express, edit the XSLT directly. Validate compiles with Saxon-HE and rejects forbidden constructs with a clear code.
04AI from examples
Show, don’t specify
Give input → expected-output pairs and a plain instruction. The AI proposes a mapping, the server compiles it, runs every example and feeds the diffs back — up to four rounds.
Any model, your rules
Claude, Gemini, Ollama, LM Studio, vLLM, OpenRouter and many more. Budgets, rate limits and a local-only switch per project. AI never deploys anything by itself.
05Versioning & Git
Every save is a version
Immutable versions with message, label and origin (manual, mapper, AI, import, restore). Diff and restore in one click.
One commit per save
Each project has a Git repository — internal, or pushed to GitHub, GitLab, Gitea, Bitbucket, Azure DevOps or any HTTPS remote. Check-out keeps one editor at a time.
06Environments
DEV → TEST → PROD
Install a pipeline version in an environment, then promote it along your chain. Upgrades, downgrades and uninstalls land in an append-only history.
Side by side when you need it
Single mode replaces the installed version; parallel mode runs several versions at once, addressed by number. Every answer names the version that ran.

From sample to production

Nothing reaches the runtime by accident
  1. 01
    Develop
    Map visually, write XSLT or let AI propose from your examples. Every save is the next draft version.
    Result: Versioned mapping, one Git commit
  2. 02
    Validate
    Compile with Saxon-HE, resolve modules, reject unsafe constructs and record paths that cannot stream.
    Result: Built version or a clear problem code
  3. 03
    Test
    Test cases compare exact or normalized XML / JSON. Turn any mapping example into a test case with one click.
    Result: Green suite per version
  4. 04
    Pin
    A pipeline save pins the exact component versions it runs. A newer mapping changes nothing until you pin it.
    Result: Immutable pipeline version
  5. 05
    Deploy & promote
    All tests must pass before the first environment. Then promote through the chain, hot-swapped without restarts.
    Result: Live in DEV, TEST, PROD
Runtime API

One POST. The document streams back.

The runtime is stateless and has its own security chain: an API key per environment, no session, no cookie. Send XML, JSON, gzip, a file upload or an MTOM package; the result is written straight to the response while the input is still being read.

  • 01REST endpoint per pipeline, or a specific installed version with /v/{n}
  • 02SOAP 1.1 / 1.2 endpoint with MTOM / XOP in and out, faults with stable codes
  • 03Captured fields as JSON with Accept: application/json
  • 04RFC 9457 problem JSON for every failure — never half a document presented as success

Every pipeline, documented and callable

Project → Integration · API explorer
merlin.acme.example/projects/orders/integration

Captured from MerlinXSL with demo data: the runtime API of project Orders in the same explorer as the portal API — an endpoint per pipeline, version and SOAP binding, ready-to-paste clients from curl to COBOL, SQL and notebooks, the stable problem codes, and a live call with a PROD key.

How it stays fast

Hot-path rules
01
Compile once, run many
Every installed version is compiled at deploy into an immutable registry, swapped through one reference. Lookups take no lock and no database call.
02
Never a DOM, never a String
XML goes from the request stream into a TinyTree; JSON from Jackson events straight into the tree shape XSLT expects. Output is written straight to the socket.
03
Our own streaming
Saxon-HE cannot stream, so MerlinXSL does: path automata over StAX and Jackson events, early exit, and split mode that runs one record at a time.
04
Virtual threads
One virtual thread per request, a watchdog per run, statistics in lock-free counters flushed in one batch — never a write per request.
Benchmark results by input size
Benchmark1 KB1 MB100 MB
Transform XML37 µs16.1 ms1.50 s
Transform JSON40 µs25.6 ms2.58 s
Split transform (512 MiB heap)32 µs19.9 ms1.91 s
Capture, streaming, full scan18 µs7.2 ms0.74 s
Capture, streaming, early exit15 µs10 µs28 µs
Pipeline detect → transform → extract135 µs26.1 ms—

JMH, single laptop (AMD Ryzen AI 9 HX PRO 370, Linux, JVM 25, generational ZGC). Indicative; your hardware and stylesheets decide the real numbers.

A real pipeline, 792 KB in

Try it · 35 runs
#1 Detect
is-pma-document · matched
2.5 msslowest step
#2 Transform
pma-input-compact · done
1.5 ms792 KB → 8.6 KB JSON
#3 Transform
pma-output-compact · skipped
232 µscondition did not match
Mean per step over 35 runs, after 197 warm-up runs, in the pipeline’s own Try it dialog. A second session on the same document: 50 runs, 3.8 ms total (2.4 ms + 1.3 ms + 123 µs).

Per run

4.1 msmedian run, whole pipeline
189 MB/sinput throughput per median run
3.5 – 7.1ms, fastest to slowest of 35 runs
9.6 msfirst, cold run
Compiling every step took 684 ms — once, at deploy. Requests never compile; they only run.

Over 1 MB

JMH · same engine
16.1 ms1 MB XML transformed · ~62 MB/s
25.6 ms1 MB JSON transformed
1.50 s100 MB XML transformed · ~67 MB/s
2.58 s100 MB JSON transformed · ~39 MB/s
0.74 s100 MB fields captured, streaming · ~135 MB/s
28 µs100 MB, fields found early — the rest is never read
512 MiBheap enough to split 100 MB record by record
~500 MB/s10 MB MTOM attachment reassembled

Benchmarks of the engine on generated order documents (see the table above for the machine). Up to 64 MiB per runtime request by default, configurable.

■XSLT 1.0, 2.0 and 3.0 on Saxon-HE
■XPath 3.1 and JSON paths for extraction
■Split mode for documents of any size
■MTOM / XOP streamed, never buffered
■REST and SOAP runtime per environment
■Git history: one commit per save
■Test cases gate every first deploy
■Per-version run statistics and latency

A transformation engine that cannot reach out.

Stylesheets are code. MerlinXSL treats them that way: the only URIs a stylesheet can resolve are the resources of its own project. No file:, no http:, no external result-document — the wall against SSRF and XXE is built into the processor.

  • 01DTDs off, limits on depth, size, names, MTOM parts and wall-clock time
  • 02API keys stored as SHA-256, compared in constant time, scoped to one environment
  • 03Tenant → organization → user scoping checked on every access
  • 04AI output is untrusted code: same validation as an upload

Where it fits

Three ways documents move
01
Online requests
A system posts a document and waits for the answer. REST or SOAP per pipeline, one API key per environment, the result streamed back while the input is still arriving — about 40 µs of engine work for a 1 KB message.
02
Data pipelines
Messages flow between systems all day. Detect what arrived, route each message family and version to its own sub pipeline, transform, extract — every step pinned to a tested version, every run counted per pipeline version.
03
ETL & batch
Large exports and nightly files. Split mode cuts a document record by record in constant memory, extraction turns each record into typed JSON fields ready to load, and gzip or file uploads go straight in.

Sectors

XML and JSON standards we see every day
  • Banking & payments
    ISO 20022 payment initiations and statements (pain, camt), SEPA files, statement data extracted for reconciliation.
  • Insurance
    Policy, claim and broker messages in many versions, routed by detection to the mapping that fits each version.
  • E-invoicing & procurement
    Orders and ERP exports to UBL and Peppol BIS invoices, credit notes and order responses, with totals captured in the same run.
  • Logistics & transport
    Shipment, booking and status messages between carriers, forwarders and warehouses; customs declarations in XML.
  • Healthcare
    HL7 FHIR resources in XML and JSON, lab and referral documents mapped between hospital and partner systems, on premise.
  • Government & public sector
    Statutory XML formats, tax and social-security filings, e-procurement — validated, versioned and kept inside your network.
  • Energy & utilities
    Market messages and meter data between suppliers, grid operators and billing, in high volume and under strict deadlines.
  • Retail & e-commerce
    Product feeds, orders and stock updates between webshop, marketplaces and ERP — JSON on one side, XML on the other.
  • Publishing & media
    Article and book XML (JATS, DITA, NewsML) transformed for web, print and syndication partners.

Ready to retire your transformation backlog?

Contact

Let's talk MerlinXSL.

Tell us about your transformation landscape, or ask for a trial licence. We reply within one business day — in Dutch or English.

Address
Schrieksesteenweg 40-42
2221 Heist-op-den-Berg (Pijpelheide)
Belgium
Hours
Mon – Fri, 8:30 – 18:00
No newsletter, no spam.