ODT (OpenDocument Text) is the ISO standard format for text documents in LibreOffice and Apache OpenOffice. It is a ZIP file containing XML, images, and metadata — fully open and free of proprietary software dependencies.
ODT vs DOCX: comparison
| Feature | ODT | DOCX |
|---|---|---|
| Standard | ISO/IEC 26300 | ECMA-376 |
| Developed by | OASIS / ISO | Microsoft |
| Support | LibreOffice, OpenOffice, Google Docs | Word, LibreOffice, Google Docs |
| Government adoption | Very high (EU, Spain) | High |
Internal structure
unzip -l document.odt
# mimetype, content.xml, styles.xml, meta.xml, settings.xml, META-INF/manifest.xml
unzip -p document.odt content.xml | python3 -m xml.etree.ElementTree
Install odfpy
pip install odfpy
Create an ODT document
from odf.opendocument import OpenDocumentText
from odf.style import Style, TextProperties
from odf.text import P, H
doc = OpenDocumentText()
h = H(outlinelevel=1, stylename='Heading 1')
h.addText('My First ODT Document')
doc.text.addElement(h)
p = P(stylename='Text Body')
p.addText('This document was created with Python and odfpy.')
doc.text.addElement(p)
doc.save('my_document.odt')
print("ODT document created")
Extract text from an ODT
from odf.opendocument import load
from odf import teletype
def extract_odt_text(path):
doc = load(path)
lines = []
for elem in doc.text.childNodes:
if elem.qname[1] in ('p', 'h'):
line = teletype.extractText(elem).strip()
if line:
lines.append(line)
return '\n'.join(lines)
print(extract_odt_text('document.odt')[:500])
Read metadata
from odf.opendocument import load
doc = load('document.odt')
meta = doc.meta
print(f"Title: {meta.title}")
print(f"Author: {meta.creator}")
print(f"Date: {meta.creation_date}")
print(f"Pages: {meta.page_count}")
Convert with LibreOffice CLI
libreoffice --headless --convert-to docx document.odt
libreoffice --headless --convert-to pdf document.odt
libreoffice --headless --convert-to pdf --outdir ./pdfs/ document.odt
libreoffice --headless --convert-to pdf *.odt # batch
Batch conversion with Python
import subprocess
from pathlib import Path
def convert_odt_to_pdf(input_dir, output_dir):
source = Path(input_dir)
dest = Path(output_dir)
dest.mkdir(parents=True, exist_ok=True)
for odt in sorted(source.glob('*.odt')):
r = subprocess.run(
['libreoffice', '--headless', '--convert-to', 'pdf',
'--outdir', str(dest), str(odt)],
capture_output=True, text=True,
)
if r.returncode == 0:
pdf = odt.stem + '.pdf'
size = (dest / pdf).stat().st_size / 1024
print(f"OK → {pdf} ({size:.0f} KB)")
else:
print(f"ERROR: {r.stderr[:200]}")
convert_odt_to_pdf('odt_documents/', 'generated_pdfs/')
When to use ODT
- Long-lived documents: more stable than DOCX across software versions
- Government and public sector: required by many European administrations
- Avoiding Microsoft dependency: completely free and open ecosystem