Pandas read_xml(): Read XML Data into a DataFrame

Reading an XML file into a Pandas DataFrame using read_xml

pandas.read_xml() reads XML data and converts selected XML elements and attributes into a Pandas DataFrame. It can read XML from a file, file-like object or supported URL and can select repeating nodes with XPath.

Download student.xml


Syntax of pandas.read_xml() 🔝

pd.read_xml(
    path_or_buffer,
    xpath='./*',
    namespaces=None,
    elems_only=False,
    attrs_only=False,
    names=None,
    dtype=None,
    converters=None,
    parse_dates=None,
    encoding='utf-8',
    parser='lxml',
    stylesheet=None,
    iterparse=None,
    compression='infer',
    storage_options=None
)

Some commonly used parameters are:

ParameterPurpose
path_or_bufferXML file path, supported URL or file-like object.
xpathSelects the XML elements that should become DataFrame rows.
parserSelects lxml or etree.
attrs_onlyRead attributes from the selected XML elements.
elems_onlyRead child elements while excluding attributes.
namespacesMaps namespace prefixes used by XPath to namespace URIs.
namesAssigns column names to the resulting DataFrame.
dtypeControls DataFrame column data types.
parse_datesConverts selected columns to datetime values.
iterparseProcesses repeating elements in very large local XML files more efficiently.

Read an XML File into a DataFrame 🔝

The sample student.xml file contains repeating <Row> elements. Each Row represents one student.

import pandas as pd

df=pd.read_xml('student.xml', xpath='.//Row', parser='etree')
print(df.head())
Output
   id        name  class  mark  gender
0   1    John Deo   Four    75  female
1   2    Max Ruin  Three    85    male
2   3      Arnold  Three    55    male
3   4  Krish Star   Four    60  female
4   5   John Mike   Four    60  female

Each selected <Row> becomes one DataFrame row, while its child elements become DataFrame columns.

Using a Windows Path

A raw string is convenient when the XML file is stored at an absolute Windows path.

df=pd.read_xml(r'E:\testing\data\student.xml', xpath='.//Row', parser='etree')

The r prefix prevents backslashes from being interpreted as escape sequences.

Select XML Nodes with XPath 🔝

The xpath parameter tells Pandas which repeating XML elements should become rows.

df=pd.read_xml('student.xml', xpath='.//Row', parser='etree')

Here:

'.//Row'

selects all <Row> elements below the current XML root.

Default XPath

If xpath is not supplied, the current default is:

'./*'

This selects the direct child elements of the XML root. Explicit XPath is useful when the required records are deeper in the document.

lxml vs etree Parser 🔝

read_xml() supports two XML parser choices:

ParserUse
lxmlDefault parser. Supports more capable XPath expressions and XSLT stylesheets. The lxml package is required.
etreeUses Python's standard ElementTree parser. Suitable for simpler XPath expressions and does not require lxml.

Using etree

df=pd.read_xml('student.xml', xpath='.//Row', parser='etree')

Using lxml

df=pd.read_xml('student.xml', xpath='.//Row', parser='lxml')

If required, lxml can be installed with:

python -m pip install lxml

Read XML Stored in a Python String 🔝

When XML markup already exists as a Python string, wrap it in StringIO before passing it to read_xml().

from io import StringIO
import pandas as pd

xml_data='''<Students>
    <Student id="1" name="John Deo" class="Four">Passed</Student>
    <Student id="2" name="Max Ruin" class="Three">Failed</Student>
    <Student id="3" name="Arnold" class="Three">Passed</Student>
</Students>'''

df=pd.read_xml(StringIO(xml_data), parser='etree')
print(df)
Output
   id      name  class Student
0   1  John Deo   Four  Passed
1   2  Max Ruin  Three  Failed
2   3    Arnold  Three  Passed

Read XML Attributes and Child Elements 🔝

An XML record can contain both attributes and child elements.

from io import StringIO
import pandas as pd

xml_data='''<Students>
    <Student id="1">
        <name>John Deo</name>
        <class>Four</class>
        <mark>75</mark>
    </Student>
    <Student id="2">
        <name>Max Ruin</name>
        <class>Three</class>
        <mark>85</mark>
    </Student>
</Students>'''

df=pd.read_xml(StringIO(xml_data), xpath='.//Student', parser='etree')
print(df)
Output
   id      name  class  mark
0   1  John Deo   Four    75
1   2  Max Ruin  Three    85

The id attribute and the child elements are all included.

Read Only XML Attributes with attrs_only=True 🔝

Use attrs_only=True when the selected XML elements store the required data in attributes.

from io import StringIO
import pandas as pd

xml_data='''<Students>
    <Student id="1" name="John Deo" class="Four">Passed</Student>
    <Student id="2" name="Max Ruin" class="Three">Failed</Student>
    <Student id="3" name="Arnold" class="Three">Passed</Student>
</Students>'''

df=pd.read_xml(StringIO(xml_data), xpath='.//Student', parser='etree', attrs_only=True)
print(df)
Output
   id      name  class
0   1  John Deo   Four
1   2  Max Ruin  Three
2   3    Arnold  Three

The text values Passed and Failed are not included because only attributes are requested.

Read Only Child Elements with elems_only=True 🔝

elems_only=True performs the opposite type of filtering: child elements are read while attributes of the selected record elements are excluded.

from io import StringIO
import pandas as pd

xml_data='''<Students>
    <Student id="1">
        <name>John Deo</name>
        <class>Four</class>
        <mark>75</mark>
    </Student>
    <Student id="2">
        <name>Max Ruin</name>
        <class>Three</class>
        <mark>85</mark>
    </Student>
</Students>'''

df=pd.read_xml(StringIO(xml_data), xpath='.//Student', parser='etree', elems_only=True)
print(df)
Output
       name  class  mark
0  John Deo   Four    75
1  Max Ruin  Three    85

The id attributes are excluded.

Read XML with Namespaces 🔝

XML namespaces distinguish element names that belong to different vocabularies. Supply a dictionary that maps the XPath prefix to the namespace URI.

from io import StringIO
import pandas as pd

xml_data='''<ns:Students xmlns:ns="http://example.com/ns">
    <ns:Student id="1" name="John Deo" class="Four">Passed</ns:Student>
    <ns:Student id="2" name="Max Ruin" class="Three">Failed</ns:Student>
</ns:Students>'''

namespaces={'ns': 'http://example.com/ns'}

df=pd.read_xml(StringIO(xml_data), xpath='.//ns:Student', namespaces=namespaces)
print(df)
Output
   id      name  class Student
0   1  John Deo   Four  Passed
1   2  Max Ruin  Three  Failed

Default Namespace without a Prefix

If an XML document declares a default namespace:

<Students xmlns="http://example.com/ns">

create a temporary prefix for use in the XPath expression:

namespaces={'doc': 'http://example.com/ns'}

df=pd.read_xml('student.xml', xpath='.//doc:Student', namespaces=namespaces)

The prefix used in Python does not have to appear literally in the original XML document. It maps to the same namespace URI.

Rename DataFrame Columns with names 🔝

The names parameter can assign different column names to the parsed result.

df=pd.read_xml('student.xml', xpath='.//Row', parser='etree', names=['student_id', 'student_name', 'class_name', 'mark', 'gender'])
print(df.head())

The number and order of names must correspond to the parsed fields.

Control XML Column Data Types 🔝

Pandas normally infers column data types. Use dtype when a particular type must be preserved.

df=pd.read_xml('student.xml', xpath='.//Row', parser='etree', dtype={'id': 'Int64', 'mark': 'Int64'})
print(df.dtypes)

This is useful when XML values that look numeric should use a predictable DataFrame dtype.

Use converters for Custom Conversion

df=pd.read_xml('student.xml', xpath='.//Row', parser='etree', converters={'name': lambda value: value.strip()})

A converter function is applied while the XML data is being read.

Parse XML Date Fields 🔝

If an XML file contains a date field, use parse_dates to convert it to Pandas datetime values while reading.

from io import StringIO
import pandas as pd

xml_data='''<Students>
    <Student><name>John Deo</name><joined>2026-01-10</joined></Student>
    <Student><name>Max Ruin</name><joined>2026-02-15</joined></Student>
</Students>'''

df=pd.read_xml(StringIO(xml_data), xpath='.//Student', parser='etree', parse_dates=['joined'])
print(df.dtypes)

The joined column is parsed as a datetime column instead of remaining ordinary text.

Handling Nested XML 🔝

Deeply nested XML requires additional care. read_xml() does not automatically flatten every nested hierarchy into dotted DataFrame column names.

Consider this XML:

<Students>
    <Student>
        <id>1</id>
        <name>John Deo</name>
        <marks>
            <score1>75</score1>
            <score2>80</score2>
        </marks>
    </Student>
</Students>

Reading the Student node directly:

df=pd.read_xml('nested_student.xml', xpath='.//Student', parser='etree')

does not automatically produce columns named marks.score1 and marks.score2.

Select the Nested Repeating Level

If the required data is inside the <marks> element, select that level:

df=pd.read_xml('nested_student.xml', xpath='.//marks', parser='etree')
print(df)
Output
   score1  score2
0      75      80

This reads the children of <marks>, but parent fields such as student ID and name are no longer automatically attached to that record.

For complex XML structures, lxml can also work with XSLT stylesheets through the stylesheet parameter to transform the XML before DataFrame conversion.

Read Large XML Files with iterparse 🔝

For a very large XML document, building the complete XML tree in memory may be inefficient. The iterparse parameter processes repeating nodes incrementally.

For the Plus2net student XML structure:

import pandas as pd

df=pd.read_xml('student.xml', parser='etree', iterparse={'Row': ['id', 'name', 'class', 'mark', 'gender']})
print(df.head())

The dictionary key identifies the repeating element that represents one record. The associated list specifies the descendant elements or attributes to extract.

Common read_xml() Errors and Mistakes 🔝

1. Passing Literal XML Directly in Pandas 3.x

Avoid:

df=pd.read_xml(xml_data)

when xml_data contains the actual XML markup.

Use:

from io import StringIO

df=pd.read_xml(StringIO(xml_data))

2. Confusing a File Path with XML Markup

This remains valid because it represents a file path:

pd.read_xml('student.xml')

3. XPath Selects the Wrong Level

The XPath should normally select the repeating elements that represent DataFrame rows.

For:

<Students>
    <Row>...</Row>
    <Row>...</Row>
</Students>

use:

xpath='.//Row'

4. Expecting etree to Support Every XPath Expression

The standard etree parser supports a more limited XPath feature set. Use parser='lxml' when the XML requires more complex XPath processing.

5. Forgetting Namespace Mapping

This XML:

<ns:Student>

requires the XPath prefix to be associated with its namespace URI through namespaces.

6. Expecting Deep XML to Flatten Automatically

read_xml() is most convenient for shallow, regular XML. Deep parent-child relationships may require preprocessing or a custom XML parsing step.

7. Using attrs_only for Child Element Data

attrs_only=True ignores child element values. Use it only when attributes are the data you need.

8. Using elems_only When Attributes Are Required

elems_only=True excludes attributes from the parsed result.

9. Reading a Very Large XML File Normally

If the file is extremely large and follows a repeating structure, consider iterparse instead of loading the complete XML tree.

Summary of pandas.read_xml() 🔝

  • pd.read_xml() converts XML records into a Pandas DataFrame.
  • One repeating XML element should normally represent one DataFrame row.
  • path_or_buffer can refer to an XML file or a file-like object.
  • The default XPath is ./*.
  • Use xpath to select the elements that should become DataFrame rows.
  • lxml is the default parser and supports more capable XPath processing.
  • etree is useful for simpler XML structures without requiring the lxml package.
  • In Pandas 3.x, wrap literal XML strings with StringIO.
  • File path strings such as 'student.xml' can still be passed directly.
  • attrs_only=True extracts attributes from selected XML elements.
  • elems_only=True extracts child elements while excluding attributes.
  • namespaces maps prefixes used by XPath to XML namespace URIs.
  • A temporary prefix can be assigned when the XML uses a default namespace.
  • names can provide DataFrame column names.
  • dtype can control resulting column data types.
  • converters can apply custom conversion functions while reading.
  • parse_dates converts selected XML fields to datetime columns.
  • Deeply nested XML is not automatically flattened into dotted DataFrame columns.
  • Selecting a nested XPath level may omit information stored in parent nodes.
  • Complex XML may need preprocessing, dedicated XML parsing or XSLT transformation.
  • iterparse is useful for very large local XML files with repeating records.
Pandas Input/Output to_xml() Python XML Data Import Export with Tkinter and Pandas




Subscribe to our YouTube Channel here



plus2net.com







Python Video Tutorials
Python SQLite Video Tutorials
Python MySQL Video Tutorials
Python Tkinter Video Tutorials
We use cookies to improve your browsing experience. . Learn more
HTML MySQL PHP JavaScript ASP Photoshop Articles Contact us
©2000-2026   plus2net.com   All rights reserved worldwide Privacy Policy Disclaimer