Convert DOCX to Text by Unzipping XML in Python
Extract plain text from a .docx file by unzipping the container and parsing word/document.xml with regex, using only Python's standard library.
Python code
56 linesimport zipfile
import re
from pathlib import Path
def docx_to_text_unzip_xml(docx_path: str) -> str:
"""Extract plain text from a .docx file by unzipping and parsing document.xml."""
docx_path = Path(docx_path)
if not docx_path.exists():
raise FileNotFoundError(f"File not found: {docx_path}")
with zipfile.ZipFile(docx_path, 'r') as z:
# Read the main document XML from the DOCX container
with z.open('word/document.xml') as xml_file:
xml_content = xml_file.read().decode('utf-8')
# Remove XML tags, extracting text content between paragraphs
# Split into paragraphs first, then strip tags from each
paragraphs = re.findall(r'<w:p[^>]*>(.*?)</w:p>', xml_content, re.DOTALL)
text_parts = []
for para in paragraphs:
# Remove all XML tags within the paragraph
text = re.sub(r'<[^>]+>', '', para)
# Unescape common XML entities
text = text.replace('&', '&').replace('<', '<').replace('>', '>')
text = text.replace('"', '"').replace(''', "'")
text_parts.append(text.strip())
return '\n'.join(text_parts)
if __name__ == "__main__":
# Mock example: create a minimal in-memory docx and test extraction
import io
from xml.sax.saxutils import escape
# Build a simple docx-like zip structure in memory
buf = io.BytesIO()
with zipfile.ZipFile(buf, 'w') as z:
doc_xml = (
'<?xml version="1.0" encoding="UTF-8"?>'
'<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">'
'<w:body>'
'<w:p><w:r><w:t>Hello & welcome!</w:t></w:r></w:p>'
'<w:p><w:r><w:t>Second line with <tag>.</w:t></w:r></w:p>'
'</w:body>'
'</w:document>'
)
z.writestr('word/document.xml', doc_xml)
buf.seek(0)
# Write to temp file and extract
temp_path = Path('mock_doc.docx')
temp_path.write_bytes(buf.getvalue())
result = docx_to_text_unzip_xml(str(temp_path))
print(result)
temp_path.unlink() # cleanup
Output
Hello & welcome!
Second line with <tag>.
How it works
A .docx file is a ZIP archive containing XML files, with the main content in word/document.xml. The code opens the archive with zipfile, reads that XML, and splits it into paragraphs using the tags. Each paragraph is stripped of remaining XML tags with a regex substitution, then XML entities like & and < are unescaped back to their literal characters. Joining the cleaned paragraphs with newlines produces readable text without needing third-party libraries.
Common mistakes
- Forgetting to handle namespaces — some DOCX files use namespace prefixes like w: that the regex must account for
- Assuming all text is in direct <w:t> tags — content can be nested or split across multiple runs within a paragraph
- Not unescaping XML entities, which leaves & and < in the output
Variations
- Use lxml or xml.etree.ElementTree to parse the XML structurally instead of regex
- Install python-docx and use the higher-level Document API for a more robust solution
Real-world use cases
- Building a search index by extracting content from a batch of uploaded .docx documents without heavyweight dependencies.
- Automating legal or HR document workflows where text must be pulled into a database or reporting tool.
- Creating plain-text backups or previews of Word documents in a document management system.
Sponsored
More from Automation & scripting
- Aggregate Log Errors Count by Hour in Python easy
- Automate Tweeting New Blog Posts in Python easy
- Automatically Clean Temporary Files from Applications Using Python medium
- Automatically Download the Latest Software Release from GitHub with Python medium
- Automatically Generate Charts from CSV Files with One Command medium
- Automatically Generate Hardware Inventory Reports in Python easy
Keep learning
Related tutorials and quizzes for this topic.