2011-09-30 10 views
6

Ho sperimentato la creazione di un componente aggiuntivo di Outlook 2010 in C#, utilizzando Visual Studio 2008. Sono in grado di ottenere un oggetto Microsoft.Office.Interop.Word.DocumentClass da un oggetto Microsoft.Office.Interop.Outlook.Inspector, che rappresenta l'e-mail attualmente modificata. Capisco che questo DocumentClass sia usato anche in vari altri contesti (di solito per le estensioni di Microsoft Word, non sorprendentemente).Come convertire la proprietà WordOpenXML in un System.IO.Packaging.Package?

Questa classe ha utilmente una proprietà chiamata WordOpenXML, che sembra essere una rappresentazione XML di tutti i file che costituiscono il pacchetto .docx che sarebbe salvato su disco durante il salvataggio di questo documento di Word come un .docx.

Un modo in cui questa proprietà sarebbe molto utile è se potesse essere convertito in un oggetto System.IO.Packaging.Package in memoria; vale a dire. deserializzare. Qualcuno sa se c'è un modo semplice per farlo, o devo scrivere un codice di analisi XML per farlo manualmente?

+0

Jez, perché la taglia se hai risposto alla tua stessa domanda? –

+0

L'ho capito dopo aver inserito la taglia. :-) – Jez

+0

ah, capito. si, stavo per suggerire di guardare il vecchio sito di eric white su msdn, penso di ricordare di aver visto una soluzione lì. bello vedere che è capito e documentato per riferimenti futuri. –

risposta

5

ho finito per la modifica del codice che ho trovato on-line per creare un metodo che converte WordOpenXML a un pacchetto, che viene salvato su disco:

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(); 
    } 
} 
2

ho convertito questo per VB.Net e ha aggiunto un pezzo da affrontare con allegati binari. Grazie per l'eccellente lavoro!

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