Skip to content
TablePage.ai Open the app

Preserve XML Structure When You Publish CSV Tables

Learn when XML fits better than CSV, how to split nested records into related tables, and which validation checks prevent broken public datasets online.

Share X in f
Wei Hu

XML and CSV can hold many of the same scalar values, but CSV cannot directly preserve XML’s hierarchy. To publish XML as a sortable table, choose one repeating XML element as the row, map its single-value fields to columns, and move repeated child elements into related CSV tables rather than duplicating the parent row.

Describe the XML structure; the planner shows whether you need one CSV, related tables or the original XML.

XML-to-CSV Structure Planner

Choose the shape and preservation requirements of the source.

Recommended model
Publish two related CSV tables

Use one main row per repeating record and one child-table row per repeated value. Connect them with a primary key and foreign key.

Basis: W3C Model for Tabular Data and Python ElementTree documentation. Row counts are — until the source XML is inspected.

XML and CSV Represent Different Data Shapes

XML organizes content as a hierarchy of elements and attributes. CSV organizes values into rows and columns. Conversion is therefore a data-modeling task, not a file-extension change.

Question XML CSV
Natural structure Nested tree Rectangular table
Field names Elements and attributes Usually one header row
Repeated values Child elements Extra rows or tables
Types and constraints Can use a schema Usually documented separately

Python’s ElementTree documentation describes XML as inherently hierarchical and represents it as a tree (Python ElementTree documentation). The W3C tabular-data model describes rows as having the same number of cells, with each column holding the same property across rows (W3C Model for Tabular Data).

CSV is suitable for publication only after the relevant source data can be expressed honestly in that rectangular shape. If order, mixed text and elements, namespaces, comments or schema constraints are material, retain the XML alongside any CSV derivative.

Choose the Repeating Element That Becomes a Row

Start by locating the XML element that represents one observation. It might be a record, transaction, permit, product or measurement. Each occurrence of that element should normally produce one row in the main CSV.

Consider a sample dataset containing two record elements. Each record has an id attribute, a title, date and amount. The amount has a currency attribute. A nested tags element can contain several tag children.

The first record contains these values:

Field Value
id A001
title North Bridge repair
date 2026-09-15
amount 1250.00
currency USD
tags transport; capital

The second record has ID A002, the title Library equipment, the date 2026-09-18, an amount of 875.50 USD and the tag education.

The single-value fields map naturally to columns in records.csv. Displayed vertically to keep the table readable on phones, its two data rows contain:

Field A001 A002
id A001 A002
title North Bridge repair Library equipment
date 2026-09-15 2026-09-18
amount 1250.00 875.50
currency USD USD

Attributes do not need a special CSV representation. The record’s id attribute becomes an id column, while the amount’s currency attribute becomes a currency column. Document that mapping so users can trace each output field to its XML source.

Put Repeated Children in Related CSV Tables

Do not create two copies of record A001 merely because it has two tags. Duplicating the parent row would inflate the apparent number of projects and could corrupt counts and amount totals.

Instead, create record_tags.csv with one row for each relationship:

record_id tag
A001 transport
A001 capital
A002 education

Here, records.id is the primary key and record_tags.record_id is a foreign key. This preserves the one-to-many relationship without hiding several values in one cell. Apply the same pattern to nested payments, locations, participants or other repeated groups; see linking related CSV tables.

A delimited list such as transport; capital may be acceptable for display when the tags will never be filtered, counted or joined. It is a weaker interchange format because readers must know the separator and escaping rules. A related table is safer when each child value matters independently.

Make the Converter Match the Known XML Structure

A trustworthy converter states which element becomes a row and which paths become columns. For the sample structure, an ElementTree-based Python conversion would:

  1. Parse data.xml and select each record directly under the root.
  2. Read the record’s id attribute and the text of title and date.
  3. Read the amount text and its currency attribute.
  4. Write one row to records.csv for each record.
  5. Write one row to record_tags.csv for each nested tags/tag element.

Python’s csv.DictWriter handles delimiters and quoting, so rows should not be assembled through string concatenation. RFC 4180 describes the common convention: fields containing commas, double quotes or line breaks are enclosed in double quotes, and each quote inside a quoted field is doubled (RFC 4180).

Python’s CSV documentation recommends opening files with newline=''. It also notes that CSV readers normally return strings instead of assigning data types automatically (Python csv documentation). Dates, decimals, identifiers and currencies therefore need explicit validation rather than relying on inferred spreadsheet types.

Adapt the conversion when records occur at another path, meaningful whitespace must be preserved, or values appear in different attributes or elements. Additional nested groups may require additional related tables.

XML namespaces also change selectors. ElementTree expands namespaced tags to a {URI}name form, so use expanded names or a namespace map. The same ElementTree documentation covers namespace selection and provides iterparse() for incremental processing of large XML files. Processed elements can be cleared to reduce memory use.

Validate Counts, Keys and Values Against the XML

A CSV opening successfully does not prove that the conversion preserved the data. Compare the generated files with the XML source.

  • Record count: records.csv should contain one data row for every selected XML record.
  • Primary key: id should be present and unique if it identifies a record.
  • Foreign keys: every record_tags.record_id should match an ID in records.csv.
  • Cardinality: the number of XML tag elements should equal the number of rows in record_tags.csv.
  • Missingness: determine whether a missing element, an empty element and a numeric zero have different meanings.
  • Types: validate date syntax, decimal syntax, units and currency instead of accepting spreadsheet guesses.
  • Text: inspect commas, quotation marks, line breaks and non-ASCII characters in the parsed output. Use the UTF-8 CSV checklist and CSV quoting rules where needed.

Keep the original XML, conversion logic, field mapping and validation results together. CSV alone does not retain XML element order, comments, namespaces, the distinction between attributes and child elements, or schema constraints unless those details are preserved separately.

Use the example process only with XML you trust. Python warns that attacker-controlled XML can abuse parser features for denial-of-service attacks and that safety depends in part on the Expat version used by the runtime (Python XML security guidance). Applications accepting untrusted XML need parser limits and security controls designed for that threat model.

Publish the Validated Output Tables

As of September 29, 2026, TablePage accepts CSV, TSV, XLSX and XLS uploads, but not XML, and creates a public dataset page with a filterable table (TablePage). Upload the validated records.csv as the main dataset. If tags matter for filtering or analysis, publish record_tags.csv separately and describe the record_id relationship on both pages.

Remove confidential, personal or otherwise sensitive fields before upload. Include the source, retrieval date, conversion method, field definitions and update schedule so readers understand that the tables are modeled derivatives rather than lossless copies of the XML.