Patrick's Bytes

27, May 2008

Replace content of <w:t> element inside Content Controls with data bound value from Custom XML part

Filed under: LINQ,OpenXML,Word — patrickyong @ 4:47 pm

In my previous post I discovered that Content Controls in WordprocessingML files which has data binding to a CustomXML part will not render properly. However, this ONLY apply if you programmatically replaces the CustomXML part but never modify the value of <w:t> within the <w:sdt> element just like in this Eric White’s video on YouTube or as per mentioned in the book [Pro SharePoint Solution Development] in Chapter 7 .

To make things clearer, lets look at the screen shots below. For a Word 2007 document with CustomXML data bound(AND also with the CustomXML modified programmatically), below is what it looks like by default when you open it with Office 2003 (or XP and 2000), the data does not appear (below).

image

Even though you see there is no problem when open it up with Office 2007 (below)

image

This is because the Compatibility Pack for Office 2007 File Format does not render the value data bound inside the <w:databinding> element but instead its take the value in <w:t> element, shown below:

<w:sdt>
– <w:sdtPr>
<w:dataBinding w:xpath=”/root[1]/name[1]” w:storeItemID=”{b6aa39be-c6d5-40ca-a66e-93dbd069104f}” />
  <w:id w:val=”3411243″ />
– <w:placeholder>
  <w:docPart w:val=”DefaultPlaceholder_22675703″ />
  </w:placeholder>
  <w:showingPlcHdr />
  <w:text />
  </w:sdtPr>
– <w:sdtContent>
– <w:p w:rsidR=”006D15FD” w:rsidRDefault=”00F43988″>
– <w:r w:rsidRPr=”00583873″>
– <w:rPr>
  <w:rStyle w:val=”PlaceholderText” />
  </w:rPr>
<w:t>Click here to enter text.</w:t>
  </w:r>
  </w:p>
  </w:sdtContent>
  </w:sdt>

So I created a generic project using the latest OpenXML SDK (April 08 CTP) and together with LINQ to XML to modify the content within <w:t> element with the value from the CustomXML part. You can download my full source code here, but basically this is how my solution works:

XNamespace w = @”http://schemas.openxmlformats.org/wordprocessingml/2006/main”;

        public void Convert(string fileName)
        {
            using (var wordDoc = WordprocessingDocument.Open(fileName, true))
            {
                var mainPart = wordDoc.MainDocumentPart;

                XmlReader reader;

                reader = XmlReader.Create(mainPart.GetStream(FileMode.Open, FileAccess.Read));

                XDocument mainXml = XDocument.Load(reader);

                string xpath;
                XElement t;
                var bindings = mainXml.Descendants(w + “dataBinding”);

This is where the magic works, grab XPath attribute value from all the <w:databinding> elements and then replace it into <w:t> element using GetValueFromCustomXmlParts method (details do refer my source code)

                foreach (XElement binding in bindings)
                {
                    xpath = binding.Attribute(w + “xpath”).Value.ToString();

                    t = binding.Parent.Parent.Descendants(w + “t”).First();
                    string textValue = GetValueFromCustomXmlParts(mainPart.CustomXmlParts, xpath, myns);

                    t.ReplaceNodes(textValue);

                }

                XmlDocument temp = new XmlDocument();
                temp.Load(mainXml.CreateReader());
                temp.Save(wordDoc.MainDocumentPart.GetStream(FileMode.Create, FileAccess.Write));
            }
        }

After that the Word 2007 document can be opened in Office 2003 and data are rendered successfully. This solution also works in other none-MS Office productivity suites such as ThinkOffice and WordPerfect.

image

Disclamer: This is just a quick fix or rather a proof of concept on how to solve the <w:databinding> element problem on a simple Word 2007 document, there are  many situations (or more complex document layout) I haven’t tested the solution on. Do download my solution at your own risk. If you bump into problems do let me know, but my help will only be on best effort basis.

By the way, here is Eric’s video on the new OpenXML SDK

[YouTube=http://www.youtube.com/watch?v=t_FYHd234ng]
YouTube – Open XML SDK demo and road map

image

Create a free website or blog at WordPress.com.