c# - 从OLE二进制字符串解析MathType MTEF数据

标签 c# openxml ole unmarshalling mathtype

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

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

base64 binary string中提取表示由MathType创建的嵌入式对象的MS-WORD Test DOCX file

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来查看是否可以通过使用代码BinaryFormatter.Deserialize(stream)将二进制字符串反序列化为IDataObject类型的对象。但这也不起作用,提示出现异常Binary stream '0' does not contain a valid BinaryHeader

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

最佳答案

Kata,您应该已经收到我的电子邮件回复,但是对于其他感兴趣的人,我们有一个示例,该示例是从我们的SDK修改而来的,我们很乐意将其发送给需要它的任何人。对于任何使用它的人来说,如果您还没有下载SDK,它可能就没有多大意义。如果您想尝试一下,请告诉我。

鲍勃·马修斯
设计科学

关于c# - 从OLE二进制字符串解析MathType MTEF数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15320088/

相关文章:

c# - 异步/等待单线程/一些线程

c# - 如何跳过循环中自动添加到DataGridView的空行?

javascript - 如何在 WebBrowser 控件中捕获 POST 的结果?

python - 如何使用 Python 编写 OLE 组件脚本

activex - 如何从 SAP 调用 ActiveX?

c# - AJAX 调用被阻止

c# - 在 c# 中使用 openxml 进行文字处理时一行中的不同样式

c# - 为什么 OpenXML 读取行两次

.net - OpemXML 命名空间

c - 让IE浏览器打开文件