OpenXML SDK和MathML

3

我使用MathML创建了一些数据块,现在需要通过OpenXML SDK将其插入到docx文件中。我听说这是可能的,但我无法做到。有人能帮我解决这个问题吗?

1个回答

11
据我所知,OpenXml SDK原生不支持演示数学标记语言(MathML)。
相反,OpenXml SDK支持Office MathML。 因此,要将演示MathML插入Word文档,我们首先需要将演示MathML转换为Office MathML。
幸运的是,Microsoft提供了一个XSL文件(名为MML2OMML.xsl)来将演示MathML转换为Office MathML。 该文件MML2OMML.xsl位于%ProgramFiles%\Microsoft Office\Office12下。 结合.Net Framework类XslCompiledTransform,我们能够将演示MathML转换为Office MathML。
接下来是从转换后的MathML创建OfficeMath对象。 OfficeMath类表示包含WordprocessingML运行时,在处理时应视为Office Open XML Math的内容。 有关更多信息,请参阅MSDN
演示MathML不包含字体信息。为了获得良好的结果,我们必须向创建的OfficeMath对象添加字体信息。
在最后一步中,我们需要将OfficeMath对象添加到我们的Word文档中。 在下面的示例中,我只是在名为template.docx的Word文档中搜索第一个Paragraph,并将OfficeMath对象添加到找到的段落中。
XslCompiledTransform xslTransform = new XslCompiledTransform();

// The MML2OMML.xsl file is located under 
// %ProgramFiles%\Microsoft Office\Office12\
xslTransform.Load("MML2OMML.xsl");

// Load the file containing your MathML presentation markup.
using (XmlReader reader = XmlReader.Create(File.Open("mathML.xml", FileMode.Open)))
{
  using (MemoryStream ms = new MemoryStream())
  {
    XmlWriterSettings settings = xslTransform.OutputSettings.Clone();

    // Configure xml writer to omit xml declaration.
    settings.ConformanceLevel = ConformanceLevel.Fragment;
    settings.OmitXmlDeclaration = true;

    XmlWriter xw = XmlWriter.Create(ms, settings);

    // Transform our MathML to OfficeMathML
    xslTransform.Transform(reader, xw);
    ms.Seek(0, SeekOrigin.Begin);

    StreamReader sr = new StreamReader(ms, Encoding.UTF8);

    string officeML = sr.ReadToEnd();

    Console.Out.WriteLine(officeML);

    // Create a OfficeMath instance from the
    // OfficeMathML xml.
    DocumentFormat.OpenXml.Math.OfficeMath om =
      new DocumentFormat.OpenXml.Math.OfficeMath(officeML);

    // Add the OfficeMath instance to our 
    // word template.
    using (WordprocessingDocument wordDoc =
      WordprocessingDocument.Open("template.docx", true))
    {
      DocumentFormat.OpenXml.Wordprocessing.Paragraph par =
        wordDoc.MainDocumentPart.Document.Body.Descendants<DocumentFormat.OpenXml.Wordprocessing.Paragraph>().FirstOrDefault();        

      foreach (var currentRun in om.Descendants<DocumentFormat.OpenXml.Math.Run>())
      {
        // Add font information to every run.
        DocumentFormat.OpenXml.Wordprocessing.RunProperties runProperties2 =
          new DocumentFormat.OpenXml.Wordprocessing.RunProperties();

        RunFonts runFonts2 = new RunFonts() { Ascii = "Cambria Math", HighAnsi = "Cambria Math" };        
        runProperties2.Append(runFonts2);

        currentRun.InsertAt(runProperties2, 0);
      }

      par.Append(om);
    }
  }
}

非常好的解决方案@Hans。但是我如何做相反的操作呢?我想将带有OMML的Word文件的XML内容转换为包含MML的纯文本..!? - serene
1
@serene:请查看我对你的问题的回答。 - Hans
@Hans,你好!谢谢你,它确实有效!我想通过C#将MathML转换为Ribbon区域中的Open Xml Math插件,但是我在PIA中找不到像“par.Append(om);”这样的方法,并且我不知道如何将WordprocessingDocument类型转换为Globals.ThisAddIn.Application.ActiveDocument类型。是否有任何方法可以在插件或右键单击按钮中执行相同的方法,以便可以批量或逐个实时将这些MathMl转换为MS方程式,谢谢! - archenoo
最优秀和有用的答案。我做了一个小改变,使用Descendants<DocumentFormat.OpenXml.Math.OfficeMath>搜索数学公式,这样也可以找到段落中间的公式。谢谢。 - too
@Hans 抱歉,我在错误的问题下添加了一条评论。我是指您对16759100的回答,关于从Word文档中导入单个方程的相反操作。可能这个更改也适用于这个答案。 - too
@Hans,非常有用的答案!我需要安装Office才能让它工作吗?我想在服务器上使用它。谢谢! - James Hao

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接