如何将WordOpenXML属性转换为system . io . package . package

本文关键字:package system io 转换 属性 WordOpenXML | 更新日期: 2023-09-27 18:10:11

我一直在尝试用Visual Studio 2008在c#中构建Outlook 2010插件。我能够从Microsoft.Office.Interop.Outlook.Inspector对象获得Microsoft.Office.Interop.Word.DocumentClass对象,它表示当前正在编辑的电子邮件。我知道这个DocumentClass也用于各种其他上下文中(通常用于Microsoft Word扩展,毫不奇怪)。

该类有一个称为WordOpenXML的属性,它似乎是构成.docx包的所有文件的XML表示,当将此Word文档保存为.docx时,这些文件将保存到磁盘。

这个属性非常有用的一种方式是,如果它可以在内存中转换为System.IO.Packaging.Package对象;ie。反序列化。有人知道是否有一种简单的方法可以做到这一点,或者我需要编写一些XML解析代码来手动完成吗?

如何将WordOpenXML属性转换为system . io . package . package

我最终修改了一些我在网上找到的代码,以创建一个将WordOpenXML转换为一个包的方法,该包保存到磁盘:

using System;
using System.Xml;
using System.Xml.XPath;
using System.Text;
using System.IO;
using System.IO.Packaging;
// [...]
// Call like this: createPackageFromWordOpenXML(wordEditor.WordOpenXML, @"C:'outputFiles'testOut.docx");
/// <summary>
/// Creates a ZIP package (ie. Word's .docx format) from a WordOpenXML string, which is saved to the file at the path specified.
/// </summary>
/// <param name="wordOpenXML">The WordOpenXML string to get the ZIP package data from.</param>
/// <param name="filePath">The path of the file to save the ZIP package to.</param>
private void createPackageFromWordOpenXML(string wordOpenXML, string filePath)
{
    string packageXmlns = "http://schemas.microsoft.com/office/2006/xmlPackage";
    Package newPkg = System.IO.Packaging.ZipPackage.Open(filePath, FileMode.Create);
    try
    {
        XPathDocument xpDocument = new XPathDocument(new StringReader(wordOpenXML));
        XPathNavigator xpNavigator = xpDocument.CreateNavigator();
        XmlNamespaceManager nsManager = new XmlNamespaceManager(xpNavigator.NameTable);
        nsManager.AddNamespace("pkg", packageXmlns);
        XPathNodeIterator xpIterator = xpNavigator.Select("//pkg:part", nsManager);
        while (xpIterator.MoveNext())
        {
            Uri partUri = new Uri(xpIterator.Current.GetAttribute("name", packageXmlns), UriKind.Relative);
            PackagePart pkgPart = newPkg.CreatePart(partUri, xpIterator.Current.GetAttribute("contentType", packageXmlns));
            // Set this package part's contents to this XML node's inner XML, sans its surrounding xmlData element.
            string strInnerXml = xpIterator.Current.InnerXml
                .Replace("<pkg:xmlData xmlns:pkg='"" + packageXmlns + "'">", "")
                .Replace("</pkg:xmlData>", "");
            byte[] buffer = Encoding.UTF8.GetBytes(strInnerXml);
            pkgPart.GetStream().Write(buffer, 0, buffer.Length);
        }
        newPkg.Flush();
    }
    finally
    {
        newPkg.Close();
    }
}

我将其转换为VB。NET,并增加了一个片段来处理二进制附件。谢谢你出色的工作!

Public Sub createDocXFromWordOpenXML(ByRef sWordOpenXML As String, ByVal sfilePath As String)
  Dim sPackageXMLNS As String = "http://schemas.microsoft.com/office/2006/xmlPackage"
  Dim docxPkg As Package
  Dim xPathDoc As XPathDocument
  Dim xpNav As XPathNavigator
  Dim xNSMgnr As XmlNamespaceManager
  Dim xpPntr As XPathNodeIterator
  Dim partURI As Uri
  Dim pkgPart As PackagePart
  Dim sInnerXML As String
  Dim bytBuffer As Byte()
  docxPkg = System.IO.Packaging.ZipPackage.Open(sfilePath, FileMode.Create)
  Try
    xPathDoc = New XPathDocument(New StringReader(sWordOpenXML))
    xpNav = xPathDoc.CreateNavigator()
    xNSMgnr = New XmlNamespaceManager(xpNav.NameTable)
    xNSMgnr.AddNamespace("pkg", sPackageXMLNS)
    xpPntr = xpNav.Select("//pkg:part", xNSMgnr)
    While xpPntr.MoveNext()
      partURI = New Uri(xpPntr.Current.GetAttribute("name", sPackageXMLNS), UriKind.Relative)
      pkgPart = docxPkg.CreatePart(partURI, xpPntr.Current.GetAttribute("contentType", sPackageXMLNS))
      sInnerXML = xpPntr.Current.InnerXml
      Select Case True
        Case sInnerXML.Contains("xmlData")
          sInnerXML = sInnerXML.Replace("<pkg:xmlData xmlns:pkg=""" & sPackageXMLNS & """>", String.Empty)
          sInnerXML = sInnerXML.Replace("</pkg:xmlData>", String.Empty)
          bytBuffer = Encoding.UTF8.GetBytes(sInnerXML)
          pkgPart.GetStream().Write(bytBuffer, 0, bytBuffer.Length)
        Case sInnerXML.Contains("binaryData")
          sInnerXML = sInnerXML.Replace("<pkg:binaryData xmlns:pkg=""" & sPackageXMLNS & """>", String.Empty)
          sInnerXML = sInnerXML.Replace("</pkg:binaryData>", String.Empty)
          bytBuffer = Convert.FromBase64String(sInnerXML)
          pkgPart.GetStream().Write(bytBuffer, 0, bytBuffer.Length)
      End Select

    End While
    docxPkg.Flush()
  Catch ex As Exception
    Throw
  Finally
    docxPkg.Close()
  End Try
End Sub