views:

47

answers:

2

I'm trying to do a find and replace in an OpenXML word document which I've openened into a MemoryStream.

using (WordprocessingDocument _document = WordprocessingDocument.Open(_ms, true))
{
    var placeHolder = _document.MainDocumentPart.Document
                          .Descendants<DocumentFormat.OpenXml.Wordprocessing.Text>()
                          .Where(node => node.InnerText.Contains("***PlaceHolderText***"))
                          .FirstOrDefault();

    placeHolder.InnerText.Replace("***PlaceHolderText***", "hello world!");
}

This doesn't work. I'm not sure why, but manipulating the document in this way doesn't seem to have any affect on the MemoryStream.

I found this blog by Eric White which does something similar, but I still can't quite get it. He uses an XDocument, so I've got something like the following:

XDocument doc = _document.MainDocumentPart.GetXDocument(); // this is an extension method
var textNodes = doc.DescendantNodes().Where(n => n.NodeType == XmlNodeType.Text);

This finds the right nodes in my document, but the problem is now I can't work out how to change the text. The System.Xml.Linq.XNodes which I end up with this way (instead of the DocumentFormat.OpenXml.Wordprocessing.Text nodes I really want) don't have an InnerText or Value property or anything like that. I can't see any way to get the text from the nodes, or update them. I tried casting the node but that didn't compile.

Am I even going in the right direction? Or is there an easier way? Any pointers would be very much appreciated, thanks.

A: 

To the first part (updating the MemoryStream). You should think about the memory stream as read only as it is passed to the Open method. The parser has read through the stream and built another in memory representation that is not connected tot he input stream. You'll have to write it back out using Save.

As for manipulating an XNode's textual content you are looking for XText.Value.

dkackman
+1  A: 

I finally got this working. Taking the first code snippet, the last line should read placeHolder.Text and not placeHolder.InnerText. Can't believe I wasted 4 hours on that! :(

fearofawhackplanet