Как преобразовать свойство WordOpenXML в System.IO.Packaging.Package? - PullRequest
6 голосов
/ 30 сентября 2011

Я экспериментировал с созданием надстройки Outlook 2010 в C #, используя Visual Studio 2008. Я могу получить объект Microsoft.Office.Interop.Word.DocumentClass из объекта Microsoft.Office.Interop.Outlook.Inspector, который представляет редактируемое в настоящий момент электронное письмо.Я понимаю, что этот DocumentClass также используется в различных других контекстах (как правило, для расширений Microsoft Word, что неудивительно).

У этого класса есть свойство WordOpenXML, которое, по-видимому, является представлением XML всехфайлы, составляющие пакет .docx, которые будут сохранены на диск при сохранении этого документа Word как .docx.

. Одним из способов, которым это свойство будет очень полезным, является его преобразование в * 1011.* объект в памяти;то есть.десериализовать это.Кто-нибудь знает, есть ли простой способ сделать это, или мне нужно написать некоторый код XML-разбора, чтобы сделать это вручную?

Ответы [ 2 ]

5 голосов
/ 03 октября 2011

В итоге я изменил какой-то код, который нашел в сети, чтобы создать метод, который преобразует 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();
    }
}
2 голосов
/ 05 октября 2011

Я преобразовал это в 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
...