EADPy
A Python library for working with Encoded Archival Description (EAD) XML documents.
Features
- Parse and manipulate EAD 2002 and EAD3 XML documents — the version is auto-detected
- Experimental support for the draft EAD 4.0 schema (unreleased; mappings may change)
- Excludes staff-only content marked
audience="internal"by default - Convert EAD to various formats (JSON, CSV)
- Tools for batch processing of EAD files
EAD Version Support
EADPy detects the EAD version from the document's schema namespace (with a
structural fallback for documents without a namespace) and exposes it as
ead.ead_version:
| Version | Namespace | ead_version |
|---|---|---|
| EAD 2002 | urn:isbn:1-931666-22-9 |
"2002" |
| EAD3 (1.1.x) | http://ead3.archivists.org/schema/ |
"ead3" |
| EAD 4.0 (draft) | https://standards.openpreservation.org/ead/v4 |
"ead4" |
All versions produce the same normalized data structure, JSON chunks, and CSV
columns, so downstream consumers don't need to care which version they were
given. Version-specific constructs are folded into the common shape: EAD3
<unitdatestructured> and <physdescstructured> are read alongside their
legacy equivalents (ArchivesSpace exports emit both), <part> children of
name and subject elements are joined, and <daoset> groups are flattened
into the digital objects list.
EAD 4.0 support is experimental — the schema has not been released and
element mappings may change. Two limitations worth knowing: EAD 4.0 has no
repository element, so repository is always None, and it has no <dao>
equivalent, so <reference href="..."> links in a component's own
description are reported as its digital objects.
A <ead> root with an unrecognized namespace raises EadParseError
(before v0.2.0 it was parsed as EAD 2002).
Internal (Unpublished) Content
Description marked audience="internal" is staff-only: ArchivesSpace exports
unpublished records this way when "include unpublished" is selected, and
repositories use it for internal-use <dao> links and processing notes.
EADPy excludes that content by default, so JSON chunks and CSV rows are
safe to index or display:
ead = eadpy.from_path("finding_aid.xml") # internal content skipped
ead = eadpy.from_path("finding_aid.xml", include_internal=True) # full archivist view
eadpy file finding_aid.xml -o output.json --include-internal
include_internal is a keyword-only argument on all four constructors. The
filter applies to
any element carrying the attribute — components, notes, digital objects,
access terms and inline markup — with one exception: <eadheader> and
<control> are never dropped, since marking the finding aid's own header
audience="internal" is a common convention and discarding it would take the
record identifier with it. If a document's entire <archdesc> is marked
internal, parsing emits a UserWarning rather than silently returning an
empty record.
Installation
Install EADPy using pip:
pip install eadpy
Install using uv:
uv tool install eadpy
EADPy requires Python 3.11 or higher.
Command-line Usage
The following command will process an EAD XML file and export it to JSON format:
eadpy file path/to/finding_aid.xml -o output.json
To export to CSV format instead:
eadpy file path/to/finding_aid.xml -o output.csv -f csv
For batch processing of multiple EAD XML files in a directory:
eadpy dir path/to/ead_directory -o path/to/output_directory
To process subdirectories recursively:
eadpy dir path/to/ead_directory -r -o path/to/output_directory
Use the verbose flag for detailed information during processing:
eadpy file path/to/finding_aid.xml -v
Run the following to view all available options:
eadpy --help
Python Usage
EADPy provides multiple ways to create an EAD instance depending on your source data:
import eadpy
# Load an EAD file from a file path
ead = eadpy.from_path("path/to/finding_aid.xml")
# Create an EAD instance from an XML string
xml_string = """<?xml version="1.0" encoding="UTF-8"?>
<ead xmlns="urn:isbn:1-931666-22-9">
<!-- EAD content here -->
</ead>"""
ead = eadpy.from_string(xml_string)
# Create an EAD instance from bytes
from eadpy import from_bytes
with open("path/to/finding_aid.xml", "rb") as f:
xml_bytes = f.read()
ead = from_bytes(xml_bytes)
# Create an EAD instance from a file-like object
from eadpy import from_file
with open("path/to/finding_aid.xml", "r") as f:
ead = from_file(f)
# Also works with StringIO or BytesIO objects
from io import StringIO, BytesIO
from eadpy import from_file, from_string, from_bytes
string_io = StringIO(xml_string)
ead = from_file(string_io)
bytes_io = BytesIO(xml_bytes)
ead = from_file(bytes_io)
Class-Based API Style
from eadpy import EAD
# Load an EAD file from a file path
ead = EAD.from_path("path/to/finding_aid.xml")
# Create an EAD instance from an XML string
ead = EAD.from_string(xml_string)
# Create an EAD instance from bytes
with open("path/to/finding_aid.xml", "rb") as f:
xml_bytes = f.read()
ead = EAD.from_bytes(xml_bytes)
# Create an EAD instance from a file-like object
with open("path/to/finding_aid.xml", "r") as f:
ead = EAD.from_file(f)
Export to JSON chunks
JSON chunks are useful for embedding or display in applications:
# Create chunks and save them to a file
chunks = ead.create_and_save_chunks("output.json")
# Or create chunks without saving
chunks = ead.create_item_chunks()
# Then save them separately if needed
ead.save_chunks_to_json(chunks, "output.json")
Export to CSV
CSV export is useful for tabular analysis:
# Create CSV data and save it to a file
csv_data = ead.create_and_save_csv("output.csv")
# Or create CSV data without saving
csv_data = ead.create_csv_data()
# Then save it separately if needed
ead.save_csv_data(csv_data, "output.csv")
API Reference
Package Level Functions
-
from_path(file_path: str, *, include_internal: bool = False) -> EAD: Creates an EAD instance from a file path. Validates that the file exists, is not a directory, and is readable. Setinclude_internal=Trueto keepaudience="internal"content. -
from_string(xml_string: str, encoding: str = None, *, include_internal: bool = False) -> EAD: Creates an EAD instance from an XML string. Any XML encoding declaration is ignored (the string is already decoded); theencodingparameter is deprecated and raises aDeprecationWarningif passed. -
from_bytes(xml_bytes: bytes, *, include_internal: bool = False) -> EAD: Creates an EAD instance from XML bytes. Useful when working with binary data from HTTP responses or other sources. -
from_file(file_like_object, *, include_internal: bool = False) -> EAD: Creates an EAD instance from a file-like object with aread()method. Works with both text-based (StringIO) and binary (BytesIO) file objects.
Class Methods (Object Creation)
-
EAD.from_path(file_path: str, *, include_internal: bool = False) -> EAD: Creates an EAD instance from a file path. Validates that the file exists, is not a directory, and is readable. Setinclude_internal=Trueto keepaudience="internal"content. -
EAD.from_string(xml_string: str, encoding: str = None, *, include_internal: bool = False) -> EAD: Creates an EAD instance from an XML string. Any XML encoding declaration is ignored (the string is already decoded); theencodingparameter is deprecated and raises aDeprecationWarningif passed. -
EAD.from_bytes(xml_bytes: bytes, *, include_internal: bool = False) -> EAD: Creates an EAD instance from XML bytes. Useful when working with binary data from HTTP responses or other sources. -
EAD.from_file(file_like_object, *, include_internal: bool = False) -> EAD: Creates an EAD instance from a file-like object with aread()method. Works with both text-based (StringIO) and binary (BytesIO) file objects.
Instance Properties
ead_version -> str: The detected EAD version of the parsed document:"2002","ead3", or"ead4".
Instance Methods (Data Export)
-
create_item_chunks() -> list: Creates item-focused chunks that include relevant information from their parent hierarchy. Returns a list of dictionaries, each containing a text representation and metadata for each item. -
save_chunks_to_json(chunks: list, output_file: str) -> None: Saves chunks to a JSON file. Takes a list of chunks and an output file path. -
create_and_save_chunks(output_file: str) -> list: Creates item-focused chunks and saves them to a JSON file. Returns the chunks that were created and saved. -
create_csv_data() -> list: Creates a flattened hierarchy representation suitable for CSV export. Returns a list of dictionaries, each representing a row in the CSV. -
save_csv_data(csv_data: list, output_file: str) -> None: Saves CSV data to a file. Takes a list of dictionaries and an output file path. -
create_and_save_csv(output_file: str) -> list: Creates flattened CSV data and saves it to a file. Returns the CSV data that was created and saved.
Command-line Reference
Global options
--version: Show the version number and exit--help: Show help message and exit
File command options
input: Path to the EAD XML file (required)-o, --output: Path to the output file-f, --format: Output format ('json' or 'csv')-v, --verbose: Print detailed information--include-internal: Keep content markedaudience="internal"(excluded by default)
Directory command options
input_dir: Path to the directory containing EAD XML files (required)-o, --output-dir: Directory for output files-f, --format: Output format ('json' or 'csv', default: 'json')-r, --recursive: Process subdirectories recursively-v, --verbose: Print detailed information--include-internal: Keep content markedaudience="internal"(excluded by default)
Development
Setting up the development environment
EADPy uses uv for dependency management and virtual environment setup.
- Clone the repository:
git clone https://github.com/nulib-labs/eadpy
cd eadpy
- Create a virtual environment and install the project with its dev dependencies:
uv sync
- Activate the virtual environment (optional —
uv runworks without it):
source .venv/bin/activate # On Unix/macOS
# or
.venv\Scripts\activate # On Windows
Running tests
uv run pytest
Changelog
See CHANGELOG.md. Note that 0.2.0 changes two default
behaviors: audience="internal" content is now excluded, and an <ead> root
with an unrecognized namespace raises EadParseError instead of being parsed
as EAD 2002.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Acknowledgements
Special thanks to the ArcLight project, which inspired the EAD processing approach taken here. Thank you to the developers and contributors of ArcLight for their work in the archival community!
License
This project is licensed under the MIT License - see the LICENSE file for details.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file eadpy-0.2.0.tar.gz.
File metadata
- Download URL: eadpy-0.2.0.tar.gz
- Upload date:
- Size: 47.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.14.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a69b5ba642c803fd895bb620133f2a66bbc234f14fdaf33db180f45b570ce57a
|
|
| MD5 |
77689456ac884b849bdf5b1f79367339
|
|
| BLAKE2b-256 |
60155581701d92852cda2cd59c2ec26f06d499839659f05a1c4eb62bd02b8d05
|
File details
Details for the file eadpy-0.2.0-py3-none-any.whl.
File metadata
- Download URL: eadpy-0.2.0-py3-none-any.whl
- Upload date:
- Size: 27.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.14.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
908086112253fdff2fdbbdd43c25970aa299002ba3239046a45b9fdcd0791122
|
|
| MD5 |
e29453173d7edf1d85dec5c644f75db3
|
|
| BLAKE2b-256 |
3aedd838de9e2c67ab4c40dcac33b9be3889f6342ecc9623dd73a0b7c30a2f93
|