SQL to XML Converter

Turn INSERT statements from a seed file, a migration or a client export into well-formed XML. You choose the root element, the row tag, whether columns become child nodes or attributes, and how NULL is written before you copy or download.

SQL to XML conversion workspace

  • Elements or attributes
  • xsi:nil support
  • Runs in your tab
Field shape

Child elements read better in a diff. Attributes give a shorter file.



SQL input.sql
XML outputWaiting for SQL
0Tables exported
0Rows parsed
0Elements written
0 BOutput size

An INSERT already has the shape XML wants

A table name, a column list, one tuple per row. That is a container, a set of field names and a set of records, which maps onto XML with nothing left over. The work sits in the details: a comma inside a quoted string must not split a row, a column called 2nd_line is not a legal element name, and a NULL is not the same thing as an empty string once a parser on the other end reads the file.

Read this first: only INSERT and REPLACE statements with literal value tuples are parsed. A CREATE TABLE block, an INSERT ... SELECT, or a Postgres COPY section is skipped without a word. If your file is mostly schema, run it through the SQL formatter first so you see what is left, then paste the INSERT sections here.

Three settings decide the whole document

The rail on the left is short on purpose. Everything else follows from these three answers.

1

Where rows live

The root element name is yours to set. Keep Wrap rows in a table node on and each table gets its own container inside the root. Turn it off and every row sits directly under the root, which suits a single table feeding an import job.

2

What a row is called

The default takes the table name and drops the plural, so orders gives <order> and catalog_items gives <catalog_item>. Pick the table name as written when a schema on the other side expects it, or a flat <row> when the consumer reads by position.

3

How a column is written

Child elements give one node per column and survive future nesting. Attributes flatten each row into a single self-closing tag, which cuts the file roughly in half on wide tables with short values.

Child elements or attributes

Both outputs are well-formed. The choice depends on who reads the file next. Here is the same row under each setting.

Elements
<order><id>5001</id><customer>Amara Okafor</customer><total>249.50</total><status>shipped</status></order>
Attributes
<order id="5001"
customer="Amara Okafor"
total="249.50"
status="shipped"/>

Elements win when values contain line breaks, when a field might later grow children of its own, or when a reviewer reads the diff of a fixture file in a pull request. Attributes win on size and on formats where a schema already declares every field as an attribute, such as older configuration loaders. A long free-text column inside an attribute turns into one enormous line with &#10; markers where the newlines were, so text bodies belong in elements.

What happens to NULL

SQL has three states for a text column: a value, an empty string, and NULL. XML has two by default, so a converter has to pick a convention and say which one it picked.

SettingOutput for a NULL columnPick it when
Empty element<note/>The reader treats missing and empty as the same thing, and you want a stable element count per row
xsi:nil<note xsi:nil="true"/>An XSD or a typed deserializer needs a real null, not an empty string. The namespace is declared on the root for you
Nothing at allThe element is left out of that rowFile size matters on a sparse table, and the consumer handles absent fields

Attributes have no equivalent of xsi:nil. Choosing it while attribute output is on writes an empty attribute value instead, and a note appears under the editors saying so. That is the one place the two settings pull against each other.

Names XML refuses to accept

Element names follow rules that column names do not. A name starts with a letter or an underscore, holds no spaces, and must not begin with the three letters xml in any casing. Real schemas break all three.

Every rewrite is listed in the parser notes below the editors, because a silently renamed field is the kind of thing you find out about three systems later. Table names keep their schema prefix, so shop.orders stays distinct from archive.orders and the two never merge into one node.

An INSERT with no column list

Dumps written by mysqldump --compact often drop the column names and rely on table order. The statement carries no names to use, so fields read column_1 through column_n based on the widest tuple, and a note tells you it happened. If an earlier INSERT for the same table did carry a column list, those names are reused instead, which covers the common case of one full statement followed by several short ones.

Indentation is not only cosmetic

Two spaces reads well in review. The single line option strips every newline and indent, which matters when the XML rides inside a request body or a database column and the whitespace would count against a size limit. On a ten thousand row export the difference runs to several megabytes. Re-indent later with the XML pretty printer when a human needs to read it again.

When XML is the wrong target

Limits worth knowing before you paste

Nothing you paste is uploaded. Parsing, conversion, copy and download all run in JavaScript on this page, so a dump holding customer rows never leaves your machine.

Questions about converting SQL to XML

Element naming, NULL handling, attributes, dialect support and what the parser skips.

Why is my row element named order instead of orders?

The default row tag takes the table name and drops the plural, because one element holds one record. A table named orders gives order, catalog_items gives catalog_item, and categories gives category. Switch the Row tag setting to keep the table name as written, or force a flat row tag when the consuming schema expects it. The table container node always keeps the full name including any schema prefix.

What is the difference between an empty element and xsi:nil?

An empty element says the field exists with no content, which most readers treat as an empty string. The xsi:nil attribute says the value is null in the typed sense, which is what an XSD-driven deserializer in Java or C# looks for before it assigns null instead of an empty string. Selecting nil adds the XMLSchema-instance namespace declaration to the root element for you. Choose omit when the reader handles absent fields and you want the smallest file.

Can I rename the root element?

Yes. Type any name into the Root element box in the settings rail and the output updates as you type. The name is sanitised the same way column names are, so spaces and leading digits are corrected rather than producing a broken document. Leave it blank and the root falls back to dataset.

My dump has five tables. Do I get five files?

You get one document containing every table, since XML allows only a single root element. Each table becomes its own container node inside that root while Wrap rows in a table node stays checked. Uncheck Include every table to export only the table selected in the preview picker, and the download is named after that table instead of sql-data.

Does it read Postgres or SQL Server dumps, not only MySQL?

Yes, as far as INSERT syntax goes. Backtick, double-quote and square-bracket identifiers are stripped from table and column names, schema prefixes such as dbo.Orders or public.users are kept, and INSERT IGNORE, INSERT OR REPLACE and REPLACE INTO are all treated as ordinary inserts. Doubled apostrophes and backslash escapes inside string literals are both handled. A Postgres COPY block is not an INSERT, so it is skipped.

Why did my column name change in the output?

XML element names cannot start with a digit, cannot contain spaces or punctuation beyond hyphen, underscore and period, and cannot begin with the letters xml in any casing. A column named 2nd line becomes _2nd_line. Every rewrite is listed in the parser notes under the editors so you know what the consuming system will see.

Are numbers written as numbers?

Everything is written as text content, because XML carries no type without a schema. A price of 249.50 and the string 249.50 produce identical markup. If the receiving system needs typed values, pair the output with an XSD that declares each field, or convert to JSON instead where numbers and strings are distinguishable in the syntax itself.

Is my SQL sent to a server?

No. Parsing, XML generation, the preview, copy and download all happen in your browser after the page loads. No request carries your input, nothing is stored between visits, and closing the tab clears both panels.