3

LibreOffice を使用して、テキスト ドキュメント (ODT 形式) を設計および作成しました。今、プログラムで特定のプレースホルダーを見つけて、データベースのテキストに置き換えたいと思っています。

PHP 用の ODT ライブラリがいくつかあることは知っていますが、ODT ファイルは (とりわけ) XML ファイルを含む単なる ZIP ファイルであるため、これは基本的な PHP を使用し、ライブラリがなくても可能であると思います。

そこで、ODT ファイルを解凍し、content.xml を変更して、フォルダーを再度圧縮する短いスクリプトを作成しました。以下に完全なコードを示します。

手動で解凍、置換、圧縮を行うことはできますが、以下の PHP スクリプトに作業を任せるとうまくいきません。LibreOffice は、ドキュメントを開くことができず、修復を試みることができると通知します (これも機能しません)。

注意を払う必要がある特別な要件はありますか? content.xml 以外のメタ ファイルを変更する必要はありますか?

if (unzipFolder('Template.odt', 'temp')) {
    $source = file_get_contents('temp'.DIRECTORY_SEPARATOR.'content.xml');
    $source = str_replace('XXXplaceholder1XXX', 'Example Value #1', $source);
    $source = str_replace('XXXplaceholder2XXX', 'Example Value #2', $source);
    file_put_contents('temp'.DIRECTORY_SEPARATOR.'content.xml', $source);

    zipFolder('temp', 'output/Document.odt');
}

function unzipFolder($zipInputFile, $outputFolder) {
    $zip = new ZipArchive;
    $res = $zip->open($zipInputFile);
    if ($res === true) {
        $zip->extractTo($outputFolder);
        $zip->close();
        return true;
    }
    else {
        return false;
    }
}

function zipFolder($inputFolder, $zipOutputFile) {
    if (!extension_loaded('zip') || !file_exists($inputFolder)) {
        return false;
    }

    $zip = new ZipArchive();
    if (!$zip->open($zipOutputFile, ZIPARCHIVE::CREATE)) {
        return false;
    }

    $inputFolder = str_replace('\\', DIRECTORY_SEPARATOR, realpath($inputFolder));

    if (is_dir($inputFolder) === true) {
        $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($inputFolder), RecursiveIteratorIterator::SELF_FIRST);

        foreach ($files as $file) {
            $file = str_replace('\\', DIRECTORY_SEPARATOR, $file);

            if (in_array(substr($file, strrpos($file, '/')+1), array('.', '..'))) {
                continue;
            }

            $file = realpath($file);

            if (is_dir($file) === true) {
                $dirName = str_replace($inputFolder.DIRECTORY_SEPARATOR, '', $file.DIRECTORY_SEPARATOR);
                $zip->addEmptyDir($dirName);
            }
            else if (is_file($file) === true) {
                $fileName = str_replace($inputFolder.DIRECTORY_SEPARATOR, '', $file);
                $zip->addFromString($fileName, file_get_contents($file));
            }
        }
    }
    else if (is_file($inputFolder) === true) {
        $zip->addFromString(basename($inputFolder), file_get_contents($inputFolder));
    }

    return $zip->close();
}

編集 #1:上記のコードは、ODT ファイルの内容を解凍して再圧縮した場合、つまりすべてのデータ操作のコメントを外した場合でも機能しません。PHP の ZipArchive 出力の形式に何か問題がありますか?

編集#2:より具体的には、zipFolder(...)すべてを壊すのは方法です。PHP に解凍を行わせることができます。文字列操作も正常に機能します ( str_replace(...))。ただし、zipFolder(...)関数がアーカイブを作成するときは開くことができませんが、手動でアーカイブを作成すると (7-Zip などを使用して) 正常に機能します。

編集 #3: PHP の再圧縮部分を 7-Zip 経由の呼び出しに置き換えるだけで機能しましたexec(...)。したがって、問題は間違いなくここで適切な ZIP アーカイブを作成することです。もちろん、移植性を高めて依存関係を少なくするためには、PHP を使用したソリューションが機能しZipArchive、7-Zip が必要ない場合はより良いでしょう。

4

1 に答える 1