Extract Plain Text from DOCX and ODT Files with PHP

Last updated: August 25, 2026.

DOCX and ODT documents are ZIP archives containing XML. PHP can extract their main XML entry with ZipArchive, parse it without loading external entities, and collect text nodes.

Text extraction function

<?php
declare(strict_types=1);

function documentText(string $path): string
{
    $extension = strtolower(pathinfo($path, PATHINFO_EXTENSION));
    $entry = match ($extension) {
        'docx' => 'word/document.xml',
        'odt' => 'content.xml',
        default => throw new InvalidArgumentException('Expected DOCX or ODT.'),
    };

    $zip = new ZipArchive();
    if ($zip->open($path, ZipArchive::RDONLY) !== true) {
        throw new RuntimeException('The document archive could not be opened.');
    }

    $xml = $zip->getFromName($entry);
    $zip->close();
    if ($xml === false) {
        throw new RuntimeException('The document body is missing.');
    }

    $document = new DOMDocument();
    if (!$document->loadXML($xml, LIBXML_NONET | LIBXML_NOERROR | LIBXML_NOWARNING)) {
        throw new RuntimeException('The document XML is invalid.');
    }

    $parts = [];
    foreach ($document->getElementsByTagName('*') as $node) {
        foreach ($node->childNodes as $child) {
            if ($child->nodeType === XML_TEXT_NODE && trim($child->nodeValue) !== '') {
                $parts[] = trim($child->nodeValue);
            }
        }
    }
    return preg_replace('/\s+/u', ' ', implode(' ', $parts)) ?? '';
}

Limitations and safety

  • Validate file type and size before opening the archive.
  • Enforce limits on archive entries and uncompressed size to prevent decompression bombs.
  • Headers, footnotes, comments, tables, and revision markup may need separate handling.
  • This returns readable text, not the original document layout.
  • Use a dedicated document library when order and formatting must be preserved.

See PHP’s ZipArchive::open() documentation for archive handling details.

admin

admin

Leave a Reply

Your email address will not be published.