我试图在C#中操纵Word 2007文档的XML。我已经设法找到并操纵了我想要的节点,但现在我似乎无法弄清楚如何将其保存回来。这是我正在尝试的:
// Open the document from memoryStream
Package pkgFile = Package.Open(memoryStream, FileMode.Open, FileAccess.ReadWrite);
PackageRelationshipCollection pkgrcOfficeDocument = pkgFile.GetRelationshipsByType(strRelRoot);
foreach (PackageRelationship pkgr in pkgrcOfficeDocument)
{
if (pkgr.SourceUri.OriginalString == "/")
{
Uri uriData = new Uri("/word/document.xml", UriKind.Relative);
PackagePart pkgprtData = pkgFile.GetPart(uriData);
XmlDocument doc = new XmlDocument();
doc.Load(pkgprtData.GetStream());
NameTable nt = new NameTable();
XmlNamespaceManager nsManager = new XmlNamespaceManager(nt);
nsManager.AddNamespace("w", nsUri);
XmlNodeList nodes = doc.SelectNodes("//w:body/w:p/w:r/w:t", nsManager);
foreach (XmlNode node in nodes)
{
if (node.InnerText == "{{TextToChange}}")
{
node.InnerText = "success";
}
}
if (pkgFile.PartExists(uriData))
{
// Delete template "/customXML/item1.xml" part
pkgFile.DeletePart(uriData);
}
PackagePart newPkgprtData = pkgFile.CreatePart(uriData, "application/xml");
StreamWriter partWrtr = new StreamWriter(newPkgprtData.GetStream(FileMode.Create, FileAccess.Write));
doc.Save(partWrtr);
partWrtr.Close();
}
}
pkgFile.Close();
我收到错误'内存流不可扩展'。有什么想法吗?
答案 0 :(得分:8)
我建议您使用Open XML SDK而不是自己破解格式。
答案 1 :(得分:2)
使用OpenXML SDK 2.0,我这样做:
public void SearchAndReplace(Dictionary<string, string> tokens)
{
using (WordprocessingDocument doc = WordprocessingDocument.Open(_filename, true))
ProcessDocument(doc, tokens);
}
private string GetPartAsString(OpenXmlPart part)
{
string text = String.Empty;
using (StreamReader sr = new StreamReader(part.GetStream()))
{
text = sr.ReadToEnd();
}
return text;
}
private void SavePart(OpenXmlPart part, string text)
{
using (StreamWriter sw = new StreamWriter(part.GetStream(FileMode.Create)))
{
sw.Write(text);
}
}
private void ProcessDocument(WordprocessingDocument doc, Dictionary<string, string> tokenDict)
{
ProcessPart(doc.MainDocumentPart, tokenDict);
foreach (var part in doc.MainDocumentPart.HeaderParts)
{
ProcessPart(part, tokenDict);
}
foreach (var part in doc.MainDocumentPart.FooterParts)
{
ProcessPart(part, tokenDict);
}
}
private void ProcessPart(OpenXmlPart part, Dictionary<string, string> tokenDict)
{
string docText = GetPartAsString(part);
foreach (var keyval in tokenDict)
{
Regex expr = new Regex(_starttag + keyval.Key + _endtag);
docText = expr.Replace(docText, keyval.Value);
}
SavePart(part, docText);
}
从这里你可以编写一个GetPartAsXmlDocument,用它做你想做的事,然后用SavePart(part,xmlString)将它传回。
希望这有帮助!
答案 2 :(得分:2)
您应该使用OpenXML SDK来处理docx文件,而不是编写自己的包装器。
答案 3 :(得分:1)
问题似乎是doc.Save(partWrtr),它是使用newPkgprtData构建的,它是使用pkgFile构建的,它从内存流加载...因为你从内存流加载它试图将文件保存回来到同一个内存流。这会导致您看到的错误。
不要将其保存到内存流,而是尝试将其保存到新文件或新内存流中。
答案 4 :(得分:0)
获取“内存流不可扩展”的问题的简短答案是: 不要从memoryStream打开文档。 所以在这方面,早期的答案是正确的,只需打开一个文件即可。
从MemoryStream打开编辑文档(根据我的经验)容易导致'内存流不可扩展'。 我想当一个编辑需要内存流扩展时会出现该消息。 我发现我可以做一些编辑但不能增加任何尺寸。 因此,f.ex删除自定义xml部分是正常的,但添加一个和一些数据不是。
因此,如果您确实需要打开内存流,则必须弄清楚如何添加可扩展的MemoryStream。 我需要这个并希望找到解决方案。
Stein-Tore Erdal
PS:刚刚注意到“2011年1月26日15:18”的回答。 不要认为这是所有情况下的答案。 我在尝试这个时遇到错误: var ms = new MemoryStream(bytes);
using (WordprocessingDocument wd = WordprocessingDocument.Open(ms, true))
{
...
using (MemoryStream msData = new MemoryStream())
{
xdoc.Save(msData);
msData.Position = 0;
ourCxp.FeedData(msData); // Memory stream is not expandable.