从'WordOpenXML'转换为In-Memory System.IO.Packaging.Package [英] Converting from 'WordOpenXML' to In-Memory System.IO.Packaging.Package
问题描述
当使用VSTO 2012操作MS Word文档时,我看到该文档具有WordOpenXML
字符串属性,它是构成.docx软件包的所有文件的XML表示形式,保存时将保存到磁盘中Word文档为.docx.
When using VSTO 2012 to manipulate an MS Word Document, I see that the document has a WordOpenXML
string property, which is an XML representation of all the files constituting the .docx package which would be saved to disk when saving this Word document as a .docx.
我想将此字符串转换为等效的System.IO.Packaging.Package
对象内存中的.
I want to convert this string to an equivalent System.IO.Packaging.Package
object in-memory.
此处的问题非常相似.实际上,OP甚至在他的问题中提到了记忆中".但是,给出的答案包括使用System.IO.Packaging.ZipPackage.Open()
方法将软件包保存到磁盘.我不想将软件包保存到磁盘,然后必须使用WordprocessingDocument.Open()
方法再次将其打开.相反,我希望所有事情都在内存中完成,而根本不涉及文件系统.
The SO question here is very similar. Indeed, the OP even mentions 'in memory' in his question. However, the answers given involve saving the Package to disk using the System.IO.Packaging.ZipPackage.Open()
method. I do not want to save the Package to disk and then have to open it again using the WordprocessingDocument.Open()
method. Rather, I want everything to be done in memory and not involve the file system at all.
我看到WordprocessingDocument.Open()
具有一个Stream
的重载.但是,我不确定如何从WordOpenXML
字符串准备这样的Stream
,尽管我怀疑上面引用的帖子给出了很多答案.
I see that WordprocessingDocument.Open()
has an overload that takes a Stream
. However, I'm not sure how I would prepare such a Stream
from the WordOpenXML
string, although I suspect the post referenced above gives much of the answer.
推荐答案
您可以使用此方法从WordOpenXml字符串获取内存中的流:
You can use this method to get an in memory stream from the WordOpenXml string:
/// <summary>
/// Returns a System.IO.Packaging.Package stream for the given word open XML.
/// </summary>
/// <param name="wordOpenXML">The word open XML.</param>
/// <returns></returns>
public static MemoryStream GetPackageStreamFromWordOpenXML(string wordOpenXML)
{
XDocument doc = XDocument.Parse(wordOpenXML);
XNamespace pkg =
"http://schemas.microsoft.com/office/2006/xmlPackage";
XNamespace rel =
"http://schemas.openxmlformats.org/package/2006/relationships";
Package InmemoryPackage = null;
MemoryStream memStream = new MemoryStream();
using (InmemoryPackage = Package.Open(memStream, FileMode.Create))
{
// add all parts (but not relationships)
foreach (var xmlPart in doc.Root
.Elements()
.Where(p =>
(string)p.Attribute(pkg + "contentType") !=
"application/vnd.openxmlformats-package.relationships+xml"))
{
string name = (string)xmlPart.Attribute(pkg + "name");
string contentType = (string)xmlPart.Attribute(pkg + "contentType");
if (contentType.EndsWith("xml"))
{
Uri u = new Uri(name, UriKind.Relative);
PackagePart part = InmemoryPackage.CreatePart(u, contentType,
CompressionOption.SuperFast);
using (Stream str = part.GetStream(FileMode.Create))
using (XmlWriter xmlWriter = XmlWriter.Create(str))
xmlPart.Element(pkg + "xmlData")
.Elements()
.First()
.WriteTo(xmlWriter);
}
else
{
Uri u = new Uri(name, UriKind.Relative);
PackagePart part = InmemoryPackage.CreatePart(u, contentType,
CompressionOption.SuperFast);
using (Stream str = part.GetStream(FileMode.Create))
using (BinaryWriter binaryWriter = new BinaryWriter(str))
{
string base64StringInChunks =
(string)xmlPart.Element(pkg + "binaryData");
char[] base64CharArray = base64StringInChunks
.Where(c => c != '\r' && c != '\n').ToArray();
byte[] byteArray =
System.Convert.FromBase64CharArray(base64CharArray,
0, base64CharArray.Length);
binaryWriter.Write(byteArray);
}
}
}
foreach (var xmlPart in doc.Root.Elements())
{
string name = (string)xmlPart.Attribute(pkg + "name");
string contentType = (string)xmlPart.Attribute(pkg + "contentType");
if (contentType ==
"application/vnd.openxmlformats-package.relationships+xml")
{
// add the package level relationships
if (name == "/_rels/.rels")
{
foreach (XElement xmlRel in
xmlPart.Descendants(rel + "Relationship"))
{
string id = (string)xmlRel.Attribute("Id");
string type = (string)xmlRel.Attribute("Type");
string target = (string)xmlRel.Attribute("Target");
string targetMode =
(string)xmlRel.Attribute("TargetMode");
if (targetMode == "External")
InmemoryPackage.CreateRelationship(
new Uri(target, UriKind.Absolute),
TargetMode.External, type, id);
else
InmemoryPackage.CreateRelationship(
new Uri(target, UriKind.Relative),
TargetMode.Internal, type, id);
}
}
else
// add part level relationships
{
string directory = name.Substring(0, name.IndexOf("/_rels"));
string relsFilename = name.Substring(name.LastIndexOf('/'));
string filename =
relsFilename.Substring(0, relsFilename.IndexOf(".rels"));
PackagePart fromPart = InmemoryPackage.GetPart(
new Uri(directory + filename, UriKind.Relative));
foreach (XElement xmlRel in
xmlPart.Descendants(rel + "Relationship"))
{
string id = (string)xmlRel.Attribute("Id");
string type = (string)xmlRel.Attribute("Type");
string target = (string)xmlRel.Attribute("Target");
string targetMode =
(string)xmlRel.Attribute("TargetMode");
if (targetMode == "External")
fromPart.CreateRelationship(
new Uri(target, UriKind.Absolute),
TargetMode.External, type, id);
else
fromPart.CreateRelationship(
new Uri(target, UriKind.Relative),
TargetMode.Internal, type, id);
}
}
}
}
InmemoryPackage.Flush();
}
return memStream;
}
这篇关于从'WordOpenXML'转换为In-Memory System.IO.Packaging.Package的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!