大化通信

大化物流開発合同会社の社員から技術発信をしていきます

PHPでwordファイルの文字列を取得する

こんにちは、大化社員のkannaです。
今回はPHPでword(docx)ファイルの文字列の取得を行ったのでそれについて記事にしました。

以前携わった案件にてwordファイルを読み込み、
特定の文字列を抜き出し置換用のテンプレートをcsvで作成するという処理があったため備忘録として書きました。

概要

PHP標準のZipArchiveを使用し
word(docx)ファイルのプレーンテキストを取得

環境

本記事での環境は以下

文字列の取得(本文のみ)

// 取得した文字列格納用
$contents = "";
// 読み込むword(docx)ファイル
$file_path = /path/to/file.docx;
// ZipArchiveクラスの初期化
$zip = new \ZipArchive();
if ($zip->open($file_path) === true) {
    // zipアーカイブからxmlファイルを取得
    $xml = $zip->getFromName("word/document.xml");
    // xmlファイルから文字列を取得
    if ($xml) {
        $dom = new \DOMDocument();
        $dom->loadXML($xml);
        $paragraphs = $dom->getElementsByTagName("p");
        foreach ($paragraphs as $p) {
            $texts = $p->getElementsByTagName("t");
            foreach ($texts as $t) {
                $contents .= $t->nodeValue;
            }
            $contents .= "\n";
        }
    }
}

$zip->open($file_path)
wordファイルを読み込みzipファイルとして開けた場合はtrueそれ以外はエラーコードが返却されます。

$xml = $zip->getFromName("word/document.xml");
wordファイルはzipファイルなため解凍した際にword/document.xmlというファイルが存在し、その中にテキスト情報が入っています。

$dom = new \DOMDocument();
$dom->loadXML($xml);
DOMDocumentを使用しxmlファイルの読み込みを行います。

$paragraphs = $dom->getElementsByTagName("p");
xmlファイルから段落のDOMNodelistを取得します。

$texts = $p->getElementsByTagName("t");
段落のDOMNodelistを回してテキストのDOMNodelistを取得します。

foreach ($texts as $t) { $contents .= $t->nodeValue; }
テキストのDOMNodelistを回して文字列の値を取得します。

ヘッダー・フッターの文字列も含めて取得を行う場合

$contents = "";
$file_path = /path/to/file.docx;
$zip = new \ZipArchive();
if ($zip->open($file_path) === true) {
    // 本文のxmlファイルをリストに追加
    $xmlFiles = ["word/document.xml"];
    for ($i = 1; $i <= $zip->numFiles; $i++) {
        $name = $zip->getNameIndex($i - 1);
        // ヘッダーとフッターのxmlファイルが存在する場合はリストに追加
        if (preg_match('/word\/header\d+\.xml/', $name) || 
        preg_match('/word\/footer\d+\.xml/', $name)) {
            $xmlFiles[] = $name;
        }
    }
    // xmlファイルから文字列の取得を行う
    foreach ($xmlFiles as $xmlFile) {
        $xml = $zip->getFromName($xmlFile);
        if ($xml) {
            $dom = new \DOMDocument();
            $dom->loadXML($xml);
            $paragraphs = $dom->getElementsByTagName("p");
            foreach ($paragraphs as $p) {
                $texts = $p->getElementsByTagName("t");
                foreach ($texts as $t) {
                    $contents .= $t->nodeValue;
                }
                $contents .= "\n";
            }
        }
    }
}

if (preg_match('/word\/header\d+\.xml/', $name) || preg_match('/word\/footer\d+\.xml/', $name))
ヘッダーとフッターは"word/header1.xml"、"word/footer1.xml"などでxmlファイルとして取得できるので
preg_matchを使用して取得しています。

PHPでwordファイルの文字列を取得するについては以上になります。
読んでくださってありがとうございます。
参考になれば幸いです。

参考サイト

今更ながらphpでword(docx)を読み込んでplain textを得る

tamago-engineer.hateblo.jp