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

C# 从OLE二进制字符串解析MathType MTEF数据,c#,openxml,ole,unmarshalling,mathtype,C#,Openxml,Ole,Unmarshalling,Mathtype,需要将MS-WORD 2003或更低版本中的MathType方程转换为MathML,以便在web上很好地呈现。MathType的内置函数“Publish to MathPage”可以很好地完成这项工作,但我想将公式转换过程集成到我的C#应用程序中。因为我找不到MathPage导出接口由MathType SDK提供的任何API引用,所以我需要自己找到一种方法来进行单独的公式转换 当前的过程是将MS-WORD 2003或以下文档转换为开放式XML格式(docx)。在docx转换之后,我可以看到Mat

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

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

表示由MathType创建的嵌入对象的

MTEF头定义:

MTEF数据保存为对象的本机数据格式。每当一个等式对象要写入OLE“流”时,就会写入一个28字节的头,后跟MTEF数据。此标头的C结构如下所示:

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

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

在header结构就绪的情况下,下面的代码尝试从嵌入的对象二进制字符串填充header结构中的信息

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.deserialize(stream),查看它是否可以将二进制字符串反序列化为IDataObject类型的对象。但它也不起作用,提示异常
二进制流“0”不包含有效的BinaryHeader

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

[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);
}