Browser-native file tools

Convert CSV to XML

Drop a CSV below — get clean, well-formed XML with the root and row tags you choose. Special characters are escaped automatically.

— or paste CSV below

How to convert CSV to XML

Drop your CSV into the converter at the top of this page, set the root tag (the wrapper around everything) and the row tag (one per CSV row), and copy the output. The tool runs entirely in your browser using PapaParse and an in-house XML serializer — no upload.

  1. Upload your CSV or paste the contents into the input.
  2. Set the root tag — the outer wrapper, e.g. rows, customers, urlset.
  3. Set the row tag — emitted once per CSV row, e.g. row, customer, url.
  4. Pick the indent — 2 or 4 spaces. The output always uses Unix line endings.
  5. Optional: enable the attribute toggle — any CSV header starting with @ becomes an XML attribute instead of a child element.
  6. Copy or download. The output starts with <?xml version="1.0" encoding="UTF-8"?> and is valid against any XML 1.0 parser.

The five XML special characters — &, <, >, ", ' — are escaped automatically. You can paste raw text containing ampersands and angle brackets without breaking the output.

CSV to XML examples

Basic conversion (all elements)

Given this CSV:

id,name,email
1,Ada,ada@lovelace.io
2,Linus,linus@kernel.example

With root tag users and row tag user:

<?xml version="1.0" encoding="UTF-8"?>
<users>
  <user>
    <id>1</id>
    <name>Ada</name>
    <email>ada@lovelace.io</email>
  </user>
  <user>
    <id>2</id>
    <name>Linus</name>
    <email>linus@kernel.example</email>
  </user>
</users>

Mixing attributes and elements

Prefix a column header with @ and turn on the attribute toggle. Given:

@id,@type,name,email
1,admin,Ada,ada@lovelace.io
2,user,Linus,linus@kernel.example

You get:

<?xml version="1.0" encoding="UTF-8"?>
<users>
  <user id="1" type="admin">
    <name>Ada</name>
    <email>ada@lovelace.io</email>
  </user>
  <user id="2" type="user">
    <name>Linus</name>
    <email>linus@kernel.example</email>
  </user>
</users>

Special characters get escaped

A CSV cell like Smith & Sons <Ltd> becomes Smith &amp; Sons &lt;Ltd&gt; in the output — valid XML, identical when parsed back.

Attributes vs elements — which should you use?

This is the most-asked question when designing XML, and the answer is mostly stylistic, but a few rules of thumb:

  • Use elements by default. They’re easier to extend later — you can add child elements or text content without rewriting consumers. Attributes are flat strings forever.
  • Use attributes for metadata about the element rather than data inside it: id, type, lang, xmlns, href. The classic test: would this still make sense if you removed it? If yes, it’s metadata — attribute. If the document loses meaning, it’s data — element.
  • Attributes can’t repeat. An element can have many <email> children; it can only have one email="..." attribute.
  • Attributes can’t contain markup. No nested elements, no CDATA. If the value might ever need structure, make it an element.
  • Attribute values can’t contain literal < or &. They have to be escaped — but that’s automatic in this tool.

For the converter above: if your CSV has a clear identifier column (id, code, sku), prefix it with @ and emit it as an attribute. Everything else is usually better as an element.

How to convert CSV to XML in Excel, Python, or online

Online (this page)

The fastest no-code path. Paste the CSV, pick the tags, copy the XML. Works for files up to about 50–100 MB depending on your machine’s RAM.

Python with pandas

Pandas 1.3+ has DataFrame.to_xml() built in:

import pandas as pd

df = pd.read_csv("data.csv")
df.to_xml("data.xml", root_name="users", row_name="user", index=False)

For attribute output, pass attr_cols=["id", "type"] and the rest become elements. Pandas uses lxml under the hood when available — install it with pip install lxml for ~10× faster serialization.

Python with the standard library

If you don’t want pandas as a dependency, the csv + xml.etree.ElementTree combo works:

import csv
import xml.etree.ElementTree as ET

root = ET.Element("users")
with open("data.csv", newline="") as f:
    for row in csv.DictReader(f):
        user = ET.SubElement(root, "user")
        for k, v in row.items():
            ET.SubElement(user, k).text = v

ET.indent(root, space="  ")
ET.ElementTree(root).write("data.xml", encoding="utf-8", xml_declaration=True)

Excel

Excel has built-in XML export but it’s bound to its own schema (<xs:schema> mapping required). The practical path: save the worksheet as CSV, then use this converter — much simpler than wrestling with Excel’s XML mapping pane.

If you have to use Excel directly: Developer tab → Source → XML Maps → Add → import a sample XML file → drag fields onto cells → Export. Microsoft’s docs cover this under “Map XML elements to cells in an XML Map.” Most teams find it easier to script with openpyxl:

from openpyxl import load_workbook
wb = load_workbook("data.xlsx")
ws = wb.active
rows = list(ws.values)
headers = rows[0]
# ...build XML the same way as the csv example above

Command line (xq / xmlstarlet)

The xq tool (a sibling of jq) handles JSON-XML round-trips. Convert CSV to JSON first (here goes the other way), then xq it to XML.

Common CSV-to-XML problems

”My XML won’t parse — invalid character at line N”

Usually one of three things: an unescaped &, a stray < or > inside a value, or a non-UTF-8 byte. The converter on this page escapes all three automatically. If you hand-edit the output, run it through an XML validator (Python’s xmllint --noout file.xml is fastest) to confirm.

”Element names can’t start with a number”

XML names must start with a letter or underscore. If your CSV has a header like 2024_total, the converter prepends an underscore to give you _2024_total. You can also rename the column in the CSV before converting.

”Spaces in column headers break everything”

XML element names can’t contain spaces. Headers like First Name become First_Name automatically. To control the exact output, rename headers to use camelCase or snake_case before conversion.

Encoding mojibake

If your CSV contains characters like café showing up as café in the XML, the source CSV is mis-encoded. Run it through the CSV encoding converter first to normalize to UTF-8, then convert.

BOM bytes in the output

Some XML parsers choke on the UTF-8 BOM (EF BB BF). The converter on this page does not emit a BOM. If your CSV has one, PapaParse strips it during parsing.

”I need namespaces / a DOCTYPE”

The converter produces a clean, namespace-free document. For RSS feeds, Atom, Open Graph, or sitemaps you’ll need to add the xmlns="..." declaration to the root tag by hand after copying — for example, change <urlset> to <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">. A future version of this tool may add namespace presets.

Privacy: nothing is uploaded

The CSV-to-XML conversion runs entirely in your browser. PapaParse handles the CSV parsing, and the XML is assembled and escaped locally — no file ever reaches a server. Verify in DevTools → Network: zero requests during conversion.

That matters when your CSV has customer records, internal IDs, or anything you wouldn’t paste into a public converter.


Other CSV tools you might need:

  • CSV to SQL — generate INSERT statements for MySQL, Postgres, SQLite.
  • JSON to CSV — flatten JSON arrays into a clean CSV.
  • CSV Viewer — open and browse a CSV in your browser without converting it.

Related tools

Frequently asked questions

  • How do I convert CSV to XML?

    Drop your CSV into the converter at the top of this page, set the root tag (the wrapper around everything) and the row tag (one per CSV row), and copy the output. The tool escapes special characters and adds the XML declaration automatically.

  • Should each CSV column become an element or an attribute?

    Elements are the safer default — they're easier to extend and read. Use attributes for short identifiers like id, type, or lang. In this tool, prefix a CSV column header with @ and turn on the attribute toggle to emit it as an attribute instead of a child element.

  • How are special characters handled?

    The five XML special characters are escaped automatically: & becomes &amp;, < becomes &lt;, > becomes &gt;, and inside attribute values " becomes &quot;. You can paste raw text with ampersands and angle brackets — the output stays valid XML.

  • What are valid root and row tag names?

    XML element names must start with a letter or underscore, and only contain letters, digits, hyphens, underscores, and dots — no spaces, no slashes, can't start with the literal string 'xml'. The tool sanitizes invalid characters to underscores so you can't accidentally produce malformed output.

  • Should I use XML or JSON for new projects?

    JSON is lighter and the default for web APIs. XML is still the right choice when you need schemas (XSD), namespaces, mixed content (text + tags), or you're working with existing XML systems — RSS feeds, sitemaps, SOAP APIs, configuration files, Office Open XML documents.

  • Can I generate an RSS feed or XML sitemap from a CSV?

    Yes — set the root tag to rss or urlset, the row tag to item or url, and use the @ attribute prefix for fields like rel or href. You may need to add namespace declarations and a wrapping <channel> element by hand depending on the spec.

  • Does it handle large CSV files?

    Conversion runs in your browser, so it's bounded by RAM. Files up to ~50–100 MB convert comfortably on a modern laptop. For multi-gigabyte files use a streaming converter like Python's lxml or xml.etree with a CSV reader.

  • Is my CSV uploaded?

    No. Parsing runs entirely in your browser using PapaParse and the XML is built locally. No file ever reaches a server — verify in DevTools → Network.