4

需要将 MS-WORD 2003 或更低版本中的 MathType 方程转换为 MathML,以便在 Web 上很好地呈现。MathType 的内置函数“Publish to MathPage”可以很好地完成这项工作,但我想将方程转换过程集成到我的 C# 应用程序中。因为我找不到任何关于 MathPage 导出接口是由 MathType SDK 提供的 API 引用,所以我需要自己想办法进行单独的方程转换。

当前的程序是将 MS-WORD 2003 或以下文档转换为 Open XML 格式(docx)。docx转换后可以看到打开的xml中保存了MathType嵌入的ole对象二进制字符串,也就是docx。然后下一步是从嵌入对象二进制字符串中解码MTEF数据,所以我尝试通过参考MathType MTEF标头的官方文档来提取MTEF。

代表 MathType 创建的嵌入对象的base64 二进制字符串是从MS-WORD 测试 DOCX 文件中提取的。

MTEF 标头定义:

MTEF 数据保存为对象的本机数据格式。每当将方程对象写入 OLE“流”时,都会写入一个 28 字节的标头,然后是 MTEF 数据。此标头的 C 结构如下:

struct EQNOLEFILEHDR {
    WORD    cbHdr;     // length of header, sizeof(EQNOLEFILEHDR) = 28 bytes
    DWORD   version;   // hiword = 2, loword = 0
    WORD    cf;        // clipboard format ("MathType EF")
    DWORD   cbObject;  // length of MTEF data following this header in bytes
    DWORD   reserved1; // not used
    DWORD   reserved2; // not used
    DWORD   reserved3; // not used
    DWORD   reserved4; // not used
};

cf 成员是调用 Windows API 函数 RegisterClipboardFormat("MathType EF") 的返回值。

然后我尝试将其转换为 C# 版本:

[StructLayout(LayoutKind.Sequential, Pack=1)]
struct EQNOLEFILEHDR
{
    public UInt16 cbHdr;
    public UInt32 version;
    public UInt16 format;
    public UInt32 size;
    public UInt32 reserved1;
    public UInt32 reserved2;
    public UInt32 reserved3;
    public UInt32 reserved4;
}

准备好标头结构后,以下代码尝试从嵌入式对象二进制字符串中填充标头结构中的信息。

foreach (EmbeddedObjectPart eop in wordDoc.MainDocumentPart.EmbeddedObjectParts)
{
    Stream stream = eop.GetStream();
    byte[] buffer = new byte[int.Parse(stream.Length.ToString())];
    using (BinaryReader reader = new BinaryReader(stream))
    {
        int res = reader.Read(buffer, 0, int.Parse(stream.Length.ToString()));
    }
    GCHandle hdl = GCHandle.Alloc(buffer, GCHandleType.Pinned);
    IntPtr intp = Marshal.AllocHGlobal(buffer.Length);
    Marshal.Copy(buffer, 0, intp, Marshal.SizeOf(typeof(EQNOLEFILEHDR)));
    EQNOLEFILEHDR header = (EQNOLEFILEHDR)Marshal.PtrToStructure(intp, typeof(EQNOLEFILEHDR));
    Marshal.FreeHGlobal(intp);
}

但是,在标头结构中填充的数据不正确,这让我认为这不是从 DOCX 文件中的嵌入对象二进制字符串中解析 MTEF 数据的正确方法。

我还查看了 MathType SDK 下载中的示例 .NET 代码,发现 IDataObject 用于包含 MathType 信息和转换程序。所以另一种方法是使用BinaryFormatter代码来查看它是否可以将二进制字符串反序列化为 IDataObject 类型的对象BinaryFormatter.Deserialize(stream)。但是也不行,提示异常Binary stream '0' does not contain a valid BinaryHeader

我尝试用来解析 MTEF 数据的方法有什么问题吗?

4

0 回答 0