Необходимо преобразовать уравнения MathType в MS-WORD 2003 или более ранних версиях в MathML, чтобы они хорошо отображались в Интернете. Встроенная функция MathType "Publish to MathPage" может очень хорошо выполнять эту работу, но я хочу интегрировать процесс преобразования уравнений в свое приложение C#. Поскольку я не смог найти никаких ссылок на API, указывающих на то, что интерфейс экспорта MathPage предоставляется пакетом SDK MathType, мне нужно найти способ самостоятельно преобразовать отдельные уравнения.
Текущая процедура заключается в преобразовании документов MS-WORD 2003 или более ранней версии в формат Open XML (docx). После преобразования docx я вижу, что двоичная строка встроенного ole-объекта MathType сохраняется в открытом xml, который является файлом docx. Затем следующим шагом является декодирование данных MTEF из двоичной строки встроенного объекта, поэтому я попытался извлечь MTEF, обратившись к официальной документации по заголовку MathType MTEF.
двоичная строка base64, представляющая встроенный объект, созданный MathType, извлекается из Тестовый файл 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 является возвращаемым значением вызова функции RegisterClipboardFormat Windows API ("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);
}
Однако данные, заполненные в структуре заголовка, неверны, что заставляет меня думать, что это неправильный подход к анализу данных MTEF из двоичной строки внедренного объекта в файле DOCX.
Я также просмотрел пример кода .NET в загружаемом SDK MathType и обнаружил, что IDataObject используется для хранения информации MathType и процедур преобразования. Таким образом, другой подход состоит в том, чтобы использовать BinaryFormatter
, чтобы увидеть, может ли он десериализовать двоичную строку в объект типа IDataObject, используя код BinaryFormatter.Deserialize(stream)
. Но это тоже не работает, вызывая исключение Binary stream '0' does not contain a valid BinaryHeader
Что-то не так с методами, которые я пытался использовать для анализа данных MTEF?