Elixir to XML Converter
Paste Elixir structs or maps. Get clean XML back.
What this tool does
You are wiring an Elixir app to a legacy SOAP endpoint, or building a fixture for an XML-RPC integration test, and you have the struct but not the envelope. Hand-writing XmlBuilder.element/3 calls for every field gets old fast. Paste the Elixir here — a single %Order{} literal, a defmodule with a defstruct, or a whole file with several modules — and you get well-formed XML back in one pass. Same shape XmlBuilder would build, without the ceremony.
The converter knows Elixir semantics. Atoms lose the leading colon — :is_paid as a map key becomes the element name is_paid, and true / false stay as text. Decimal.new("249.99") drops the wrapper and becomes 249.99. DateTime, NaiveDateTime, and Date come out as ISO-8601 strings. Nested structs (an %Order{} with a shipping_address: %Address{} field) expand in place, and nil values become empty elements instead of being dropped. Keyword lists like [sku: "SKU-101", qty: 2] are treated the same as the equivalent map.
Lists become container elements with one child per item, named after the struct type: a items: [%OrderItem{}, %OrderItem{}] field turns into <items><OrderItem/><OrderItem/></items>. That matches how SweetXml reads XML back into Elixir and what the xmerl library under the hood expects. Tuples get a <tuple> wrapper with positional children. If you paste several defmodule blocks, every defstruct lands in the output. Paste it the way it sits in your .ex or .exs file — no cleanup needed.
How to use it
Three steps. Works the same whether you paste one struct or a whole Phoenix context file.
Paste your Elixir (or try the sample)
Drop your Elixir into the left editor as-is. A defstruct, a %Struct{} literal, a plain map, a keyword list, or nested structs — all fine. Click Load Sample for a realistic Order / OrderItem / Address example.
You do not need to strip @moduledoc, remove @derive annotations, or clean up pipes and comments. Paste the Elixir code the way it looks in your editor.
Hit Convert
Click the green Convert button. The tool reads the Elixir, keeps every field, preserves nested structs, and builds the XML in one pass. A short loading indicator runs while it works.
Copy the XML
The right panel fills with indented, well-formed XML. Copy it straight into a SOAP request body, an XML-RPC call, a test fixture, or the seed file for your integration suite.
When this actually comes in handy
Phoenix apps talking to SOAP services
Your Phoenix context hands you a nice <code>%Order{}</code>. The downstream vendor only speaks SOAP. Paste the struct, get the XML envelope body, drop it into the request — no hand-crafting <code>XmlBuilder</code> trees.
XML-RPC integrations
Old WordPress plugins, legacy CMS systems, financial feeds — all still speak XML-RPC. Turn your Elixir struct into the <code><param><value><struct></code> shape the spec expects, ready to pipe through <code>HTTPoison</code>.
Legacy enterprise integrations
Bank files, EDI feeds, health-care HL7-style payloads. If a partner insists on XML, paste the Elixir model you already have and get a matching XML template — quicker than fighting with <code>xmerl</code> from scratch.
Fixtures for SweetXml round-trips
Writing a test that reads XML with SweetXml and compares it to a struct? Paste the struct, get the XML, save it as a fixture. The round-trip stays consistent.
Common questions
Can I paste multiple defmodule / defstruct blocks at once?
Yes. Paste a whole file. Every defstruct comes through with its fields intact, and nested struct references are expanded. If you include a %Struct{} literal at the bottom with actual values, the output uses those values — otherwise it emits the shape with empty elements.
How are atoms handled?
Atoms used as map/struct keys become element names (the leading colon drops — :is_paid becomes is_paid). Atom values that are booleans (true, false, nil) become the corresponding text. Other atoms are emitted as text with the colon stripped (:pending becomes pending). If you need the original atom syntax, post-process with String.to_atom/1 after parsing.
What about Decimal, DateTime, Date, NaiveDateTime?
Decimal.new("249.99") drops the wrapper and becomes 249.99. DateTime, NaiveDateTime, and Date come out as ISO-8601 strings. Time becomes HH:MM:SS. nil values become empty elements rather than being dropped — so the shape stays consistent for SweetXml round-trips.
How do lists, tuples, and keyword lists translate?
Lists of structs become container elements with one child per item, named after the struct: items: [%OrderItem{}, ...] becomes <items><OrderItem/><OrderItem/></items>. Lists of scalars become <item> children inside the container. Tuples get a <tuple> wrapper with positional children <_0/>, <_1/>. Keyword lists are treated as maps — each key becomes a child element.
What if my struct uses @derive for Jason / Poison?
The @derive annotation is a compile-time hint for JSON libraries and does not affect XML output. All struct fields are emitted by default. If you want to omit a field, remove it from the defstruct list before pasting, or wrap the value in something the converter can recognize as "skip".
Is my code stored?
Your code is sent to the backend for conversion and is not persisted — we do not log the payload. As always with online tools, if the code is genuinely sensitive, look it over before pasting.
Other tools you may need
Elixir to XML is one piece of the puzzle. These tools pair well with it: