如何将WordOpenXML属性转换为System.IO.Packaging.Package?

问题描述:

我一直在使用Visual Studio 2008在C#中构建一个Outlook 2010插件。我能够从Microsoft.Office.Interop.Outlook.Inspector对象中获得Microsoft.Office.Interop.Word.DocumentClass对象,该对象代表当前正在编辑的电子邮件。我知道这DocumentClass也用于其他各种情况(通常用于Microsoft Word扩展,毫不奇怪)。如何将WordOpenXML属性转换为System.IO.Packaging.Package?

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

这种属性的一种方式将是非常有用的,如果它可以被转换为内存中的System.IO.Packaging.Package对象;即。反序列化它。有谁知道是否有一种简单的方法来做到这一点,还是我需要编写一些XML解析代码来手动执行?

+0

jez,为什么赏金,如果你已经回答了你自己的问题? –

+0

我把赏金付诸行动后,我发现了它。 :-) – Jez

+0

啊,明白了。是的,我打算建议在msdn上看看eric white的旧网站,我想我记得在那里看到了一个解决方案。很高兴看到它被发现并记录下来供将来参考。 –

我结束了修改一些代码,我在网上找到产生它转换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,并增加了一个peice的处理与二进制附件。感谢您的出色工作!

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