我一直在尝试使用Visual Studio 2008在C#中构建Outlook 2010插件。我能够从Microsoft.Office.Interop.Word.DocumentClass
对象获取Microsoft.Office.Interop.Outlook.Inspector
对象,该对象代表电子邮件目前已编辑。我知道这个DocumentClass
也用于其他各种情况(通常用于Microsoft Word扩展,不出所料)。
该类有一个名为WordOpenXML
的属性,它似乎是构成.docx
包的所有文件的XML表示形式,当将该Word文档另存为{时,该文件将保存到磁盘中{1}}。
这个属性非常有用的一种方法是它是否可以在内存中转换为.docx
对象;即。反序列化它。有谁知道是否有一种简单的方法可以做到这一点,还是我需要编写一些XML解析代码来手动完成它?
答案 0 :(得分:5)
我最后修改了一些我在网上找到的代码,创建了一个将WordOpenXML
转换为Package的方法,该方法保存到磁盘:
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();
}
}
答案 1 :(得分:2)
我将其转换为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