使用 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(...)
可以正常工作(
编辑#3:我什至只是通过调用 7-Zip 替换 PHP 中的重新压缩部分来使其工作exec(...)
。所以问题肯定是在这里创建一个适当的 ZIP 存档。ZipArchive
为了更好的可移植性和更少的依赖,当然,如果使用 PHP 的解决方案有效并且我们不需要 7-Zip ,那就更好了。