关于python:从make4ht到odt格式的utf-8输出

关于python:从make4ht到odt格式的utf-8输出

我正在使用make4ht将文档转换为 odt,并且我希望底层content.xml采用 utf-8 编码。我使用u以下选项make4ht

make4ht -uf odt filename.tex

请考虑以下文档:

\documentclass{article}

\usepackage[utf8]{inputenc}

\begin{document}

Hello World!!!

áéíóúâêîôûüãõç.

\end{document}

结果.odt显示正确,但底层content.xml将重音字符呈现为:

<text:p text:style-name="First-line-indent">   &#xE1;&#xE9;&#xED;&#xF3;&#xFA;&#xE2;&#xEA;&#xEE;&#xF4;&#xFB;&#xFC;&#xE3;&#xF5;&#xE7;.
   </text:p>

(即使 UTF-8 标头已经到位:)<?xml version="1.0" encoding="UTF-8"?>

和:

htlatex filename.tex "xhtml,ooffice,charset=utf-8" " -cmozhtf -utf8" " -coo"

我确实得到了正确的 utf-8 编码content.xml。我还尝试将这些相同的参数传递给make4ht,但无济于事。我应该怎么做才能确保make4ht提供 utf-8 编码的.odt输出?

答案1

编辑:的开发版本make4ht现在支持ODT输出中的过滤器,因此不再需要ODT使用zip方法更新文件。

简化的构建文件可能如下所示:

local filter = require "make4ht-filter"
local utfchar = unicode.utf8.char
local process =  filter {
  function(content)
    return content:gsub("%&%#x([A-Fa-f0-9]+);", function(entity)
      -- convert hexadecimal entity to Unicode
      print(entity,utfchar(tonumber(entity, 16)))
      return utfchar(tonumber(entity, 16))
    end)
  end
}

Make:match("4oo$", process)

只需要使用 生成的临时文件名tex4ht,因此需要content.xml处理带有.4oo包含文档文本的扩展名的文件。


原始答案:

命令将Unicode 字符content.xml转义为 XML 实体xtpipes,对文件进行后期处理以修复一些与数学和部分有关的问题。xtpipes可以t4ht使用选项从命令中请求-cooxtpipesmake4ht默认使用此选项进行输出ODT

如果使用与 for 相同的参数htlatex并省略xtpipesmake4ht将产生相同的结果,带有 Unicode 字符:

make4ht sample.tex "xhtml,ooffice" " -cmozhtf -utf8" " -coo"

<text:p text:style-name="First-line-indent">   áéíóúâêîôûüãõç.

但我建议不要禁用xtpipes,因为这样最终可能会得到无效的 ODT 文件。

相反,可以使用make4ht构建文件将实体转换为 Unicode:

local mkutils = require "mkutils"
local zip = require "zip"
local utfchar = unicode.utf8.char


-- use function to change contents of the ODT file
local function update_odt(odtfilename, file_path, fn)
  -- get name of the odt file
  local odtname = mkutils.remove_extension(odtfilename) .. ".odt"
  -- open and read contents of the requested file inside ODT file
  local odtfile = zip.open(odtname)
  local local_file = odtfile:open(file_path)
  local content = local_file:read("*all")
  local_file:close()
  odtfile:close()
  -- update the content using user function
  content = fn(content)
  -- write the updated file
  local local_file_file  = io.open(file_path,"w")
  local_file_file:write(content)
  local_file_file:close()
  os.execute("zip " .. odtname .. " " .. file_path)
  os.remove(file_path)
end

Make:match("tmp$", function(name, par)
  update_odt(name, "content.xml", function(content)
    return content:gsub("%&%#x([A-Fa-f0-9]+);", function(entity)
      -- convert hexadecimal entity to Unicode
      print(entity,utfchar(tonumber(entity, 16)))
      return utfchar(tonumber(entity, 16))
    end)
  end)
end)

因为ODT文件是按照调用的相同步骤进行压缩的xtpipes,所以需要打开ODT文件,读取content.xml文件内容,然后再次打包。

那么内容似乎是正确的:

<text:p text:style-name="First-line-indent">   áéíóúâêîôûüãõç.

相关内容