Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 112119
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 11, 20262026-05-11T02:29:40+00:00 2026-05-11T02:29:40+00:00

I built a template-based document generator using the Open XML SDK (1.0) , the

  • 0

I built a template-based document generator using the Open XML SDK (1.0), the Word 2007 Content Control Toolkit and LINQ to SQL (using the CodeSmith PLINQO templates). To do this, I serialized the LINQ to SQL entities to XML by retrieving the entity using DataLoadOptions specified in the source code.

This works great, except that to initially populate the XML in my template, I currently have to copy and paste the XML from the Immediate window in VS2008 into the Content Control Toolkit, and it still has all the data from the current entity.

I’m looking for two solutions: 1) Is this a good way to build a document generator with Word 2007? 1) How can I generate just the XML I need without the data? I’ve thought of creating an XSD and then creating an empty XML document, but wasn’t sure how to do that programatically so that a business user can get the XML for the template. (That’s not a requirement, just a nice-to-have.)

Thanks for your feedback,

Ryan

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. 2026-05-11T02:29:41+00:00Added an answer on May 11, 2026 at 2:29 am

    I finally got this working, thanks to the genius of Mr. Eric White. I’ve even managed to remove the use of one of the tools mentioned above (Word 2007 Content Control Toolkit). Here are the steps I’m now taking:

    1. Make the template data-bindable.
    2. Make a copy of the template to which to save changes.
    3. Retrieve the Custom XML from the template using LINQ to XML and the Open XML SDK.
    4. Serialize the LINQ to SQL entity using the DataContractSerializer.
    5. Use LINQ to XML to find the appropriate descendant based on a) the entity name and b) the property name.
    6. Clone the Custom XML and fill it with the values from the serialized LINQ to SQL entity (this uses a modified version of Eric’s Clone() method).
    7. Replace the Custom XML in the document with the cloned and filled Custom XML (courtesy Brian Jones).
    8. Done!

    I’ve attached the extension methods I’m using for the above steps below:

    using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Xml; using System.Xml.Linq; using DocumentFormat.OpenXml.Packaging;  namespace OpenXmlDocGenerator {     /// <summary>     /// Adds extensions for making the Open XML SDK and LINQ to XML easier to use.     /// </summary>     public static class OpenXmlExtensions     {         #region fields          private static readonly XNamespace w = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';         private static readonly XName r = w + 'r';         private static readonly XName ins = w + 'ins';         private static readonly XNamespace ds = 'http://schemas.openxmlformats.org/officeDocument/2006/customXml';          #endregion          #region methods          /// <summary>         /// Adds the custom XML part to the main document part.         /// </summary>         /// <param name='document'>The main document part.</param>         /// <param name='customXml'>The custom XML.</param>         /// <returns>The <see cref='CustomXmlPart' />.</returns>         public static void AddCustomXmlPart(this MainDocumentPart document, XDocument customXml)         {             CustomXmlPart customXmlPart = document.AddNewPart<CustomXmlPart>();             customXmlPart.PutXDocument(customXml);         }          /// <summary>         /// Adds the custom XML part with a custom XML properties to the main document part.         /// </summary>         /// <param name='mainPart'>The main document part.</param>         /// <param name='customXml'>The custom XML.</param>         /// <param name='customXmlProperties'>The custom XML properties.</param>         public static void AddCustomXmlPart(             this MainDocumentPart mainPart, XDocument customXml, XDocument customXmlProperties)         {             CustomXmlPart customXmlPart = mainPart.AddNewPart<CustomXmlPart>();             CustomXmlPropertiesPart customXmlPropertiesPart = customXmlPart.AddNewPart<CustomXmlPropertiesPart>();             customXmlPropertiesPart.PutXDocument(customXmlProperties);             customXmlPart.PutXDocument(customXml);         }          /// <summary>         /// Clones the specified element.         /// </summary>         /// <param name='element'>The element.</param>         /// <returns>The cloned <see cref='XElement' />.</returns>         public static XElement Clone(this XElement element)         {             return new XElement(element.Name,                        element.Attributes(),                        element.Nodes().Select(n =>                           {                               XElement e = n as XElement;                               if (e != null)                               {                                   return e.Clone();                               }                                return n;                           }                        ),                        (!element.IsEmpty && !element.Nodes().OfType<XText>().Any()) ? string.Empty : null                    );         }          /// <summary>         /// Fills the specified element with the provided <paramref name='entityMap'/>.         /// </summary>         /// <param name='element'>The element.</param>         /// <param name='entityMap'>The entity map between the custom XML elements and the entity values.</param>         /// <returns>The filled <see cref='XElement'/>.</returns>         public static XElement Fill(this XElement element, IDictionary<string, object> entityMap)         {             return new XElement(element.Name,                        element.Attributes(),                        element.Nodes().Select(node =>                           {                               XElement childElement = node as XElement;                               if (childElement != null)                               {                                   // If the child element does not have elements,                                   // attempt to insert the value from the entity map;                                   // otherwise, recursively call the Fill() to find                                   // child elements to fill.                                   return !childElement.HasElements                                              ? InsertValue(childElement, entityMap)                                              : childElement.Fill(entityMap);                               }                                return node;                           }                        ),                        (!element.IsEmpty && !element.Nodes().OfType<XText>().Any()) ? string.Empty : null                    );         }          /// <summary>         /// Gets a descendant element of the specified element the by the descendant's name.         /// </summary>         /// <param name='element'>The element from which to find the descendant element.</param>         /// <param name='descendantElementName'>Name of the descendant element.</param>         /// <returns>The descendant <see cref='XElement' />.</returns>         /// <exception cref='ArgumentNullException'>Thrown when the <paramref name='element'/> is null.</exception>         public static XElement GetDescendantByName(this XElement element, string descendantElementName)         {             if (element == null)             {                 throw new ArgumentNullException('element');             }              return element.Elements().DescendantsAndSelf().FirstOrDefault(e => e.Name.LocalName == descendantElementName);         }          /// <summary>         /// Gets the custom XML from the main document part.         /// </summary>         /// <param name='mainPart'>The main document part.</param>         /// <returns>The custom XML as a <see cref='XElement' />.</returns>         public static XElement GetCustomXml(this MainDocumentPart mainPart)         {             CustomXmlPart customXmlPart = mainPart.GetPartsOfType<CustomXmlPart>().FirstOrDefault();             return customXmlPart == null ? null : customXmlPart.GetXDocument().Root;         }          /// <summary>         /// Gets the XDocument from the document part.         /// </summary>         /// <param name='part'>The document part.</param>         /// <returns>The XDocument.</returns>         public static XDocument GetXDocument(this OpenXmlPart part)         {             XDocument xdoc = part.Annotation<XDocument>();             if (xdoc != null)             {                 return xdoc;             }              using (StreamReader streamReader = new StreamReader(part.GetStream()))             using (XmlReader xmlReader = XmlReader.Create(streamReader))             {                 xdoc = XDocument.Load(xmlReader);             }              part.AddAnnotation(xdoc);             return xdoc;         }          /// <summary>         /// Determines whether the specified document is bindable.         /// </summary>         /// <param name='document'>The document.</param>         /// <returns>         ///     <c>true</c> if the specified document has a <see cref='CustomXmlPart' />; otherwise, <c>false</c>.         /// </returns>         public static bool IsBindable(this WordprocessingDocument document)         {             return document.MainDocumentPart.GetPartsCountOfType<CustomXmlPart>() > 0;         }          /// <summary>         /// Serializes the XDocument back into the package.         /// </summary>         /// <param name='part'>The document part.</param>         /// <param name='xdoc'>The <see cref='XDocument' />.</param>         public static void PutXDocument(this OpenXmlPart part, XDocument xdoc)         {             if (xdoc != null)             {                 using (Stream stream = part.GetStream(FileMode.Create, FileAccess.ReadWrite))                 using (XmlWriter partWriter = XmlWriter.Create(stream))                 {                     xdoc.Save(partWriter);                 }             }         }          /// <summary>         /// Removes the custom XML parts.         /// </summary>         /// <param name='mainPart'>The main document part.</param>         public static void RemoveCustomXmlParts(this MainDocumentPart mainPart)         {             if (mainPart.CustomXmlParts.Count() > 0)             {                 mainPart.DeleteParts(mainPart.CustomXmlParts);             }         }          /// <summary>         /// Replaces the custom XML in the main document mainPart.         /// </summary>         /// <param name='mainPart'>The main document part.</param>         /// <param name='customXml'>The custom XML.</param>         public static void ReplaceCustomXml(this MainDocumentPart mainPart, XElement customXml)         {             if (customXml != null)             {                 mainPart.RemoveCustomXmlParts();                  CustomXmlPart customXmlPart = mainPart.AddNewPart<CustomXmlPart>();                 using (Stream stream = customXmlPart.GetStream(FileMode.Create, FileAccess.ReadWrite))                 using (XmlWriter writer = XmlWriter.Create(stream))                 {                     customXml.Save(writer);                 }                }         }          /// <summary>         /// Translates the <paramref name='source'/> collection using the <paramref name='translate'/>,         /// then concatenates and returns the result.         /// </summary>         /// <typeparam name='T'>The type of the items in the source.</typeparam>         /// <param name='source'>The source.</param>         /// <param name='translate'>The translation function to perform on each item in the source.</param>         /// <returns>The concatenated contents of the source collection.</returns>         public static string StringConcatenate<T>(this IEnumerable<T> source, Func<T, string> translate)         {             return source.Aggregate(new StringBuilder(), (s, i) => s.Append(translate(i)), s => s.ToString());         }          /// <summary>         /// Concatenates the items in the <paramref name='source'/> and returns the result.         /// </summary>         /// <param name='source'>The source.</param>         /// <returns>The concatenated contents of the source collection.</returns>         public static string StringConcatenate(this IEnumerable<string> source)         {             return source.Aggregate(new StringBuilder(), (s, i) => s.Append(i), s => s.ToString());         }          /// <summary>         /// Creates a bindable version of the <see cref='WordprocessingDocument' />.         /// </summary>         /// <param name='document'>The document.</param>         /// <returns>The <see cref='WordprocessingDocument' />.</returns>         /// <seealso cref='http://blogs.msdn.com/ericwhite/archive/2008/10/19/creating-data-bound-content-controls-using-the-open-xml-sdk-and-linq-to-xml.aspx'/>         public static WordprocessingDocument ToBindable(this WordprocessingDocument document)         {             foreach (MainDocumentPart mainPart in document.GetPartsOfType<MainDocumentPart>())             {                 mainPart.RemoveCustomXmlParts();                  Guid id = Guid.NewGuid();                 XDocument customXml = mainPart.CreateCustomXml();                 XDocument customXmlProperties = CreateCustomXmlProperties(id);                 mainPart.AddCustomXmlPart(customXml, customXmlProperties);                  XDocument partXDoc = mainPart.GetXDocument();                 AddDataBinding(partXDoc, id);                 mainPart.PutXDocument(partXDoc);             }              return document;         }          #region --private          /// <summary>         /// Adds data binding to the content controls.         /// </summary>         /// <param name='mainDocumentXDoc'>The main document <see cref='XDocument' />.</param>         /// <param name='id'>The id.</param>         private static void AddDataBinding(XDocument mainDocumentXDoc, Guid id)         {             foreach (XElement sdt in mainDocumentXDoc.Descendants(w + 'sdt'))             {                 sdt.Element(w + 'sdtPr')                     .Element(w + 'placeholder')                     .AddAfterSelf(                     new XElement(w + 'dataBinding',                         new XAttribute(w + 'xpath',                             '/root/' + sdt.Element(w + 'sdtPr')                                 .Element(w + 'tag')                                 .Attribute(w + 'val').Value),                         new XAttribute(w + 'storeItemID',                             '{' + id.ToString().ToUpper() + '}')                     )                 );             }         }          /// <summary>         /// Creates the custom XML from the existing content controls.         /// </summary>         /// <param name='mainPart'>The main document part.</param>         /// <returns>The custom XML as a <see cref='XDocument' />.</returns>         private static XDocument CreateCustomXml(this MainDocumentPart mainPart)         {             XElement customXml =                 new XElement('root',                     mainPart                     .GetXDocument()                     .Descendants(w + 'sdt')                     .Select(sdt =>                         new XElement(                             sdt.Element(w + 'sdtPr')                                 .Element(w + 'tag')                                 .Attribute(w + 'val').Value,                              GetTextFromContentControl(sdt).Trim())                     )                 );              return new XDocument(customXml);         }          /// <summary>         /// Creates the custom XML property part contents.         /// </summary>         /// <param name='id'>The id.</param>         /// <returns>The contents of the custom XML properties part.</returns>         private static XDocument CreateCustomXmlProperties(Guid id)         {             return new XDocument(                        new XElement(ds + 'datastoreItem',                            new XAttribute(ds + 'itemID',                                '{' + id.ToString().ToUpper() + '}'),                            new XAttribute(XNamespace.Xmlns + 'ds',                                ds.NamespaceName),                            new XElement(ds + 'schemaRefs')                        )                    );         }          /// <summary>         /// Gets the text from content control.         /// </summary>         /// <param name='contentControlNode'>The content control node.</param>         /// <returns>The string representation of the value in the content control.</returns>         static string GetTextFromContentControl(XElement contentControlNode)         {             return contentControlNode.Descendants(w + 'p')                 .Select(p => p.Elements()                                  .Where(z => z.Name == r || z.Name == ins)                                  .Descendants(w + 't')                                  .StringConcatenate(element => (string)element) + Environment.NewLine)                 .StringConcatenate();         }          /// <summary>         /// Inserts the value from the <paramref name='entityMap'/> into the <paramref name='childElement'/>.         /// </summary>         /// <param name='childElement'>The child element.</param>         /// <param name='entityMap'>The entity map.</param>         private static XElement InsertValue(XElement childElement, IDictionary<string, object> entityMap)         {             string name = childElement.Name.LocalName;              if (entityMap.Keys.Contains(name))             {                 childElement.SetValue(entityMap[name] ?? string.Empty);             }             else             {                 childElement.SetValue(string.Empty);             }              return childElement;         }          #endregion          #endregion     } } 
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Ask A Question

Stats

  • Questions 160k
  • Answers 160k
  • Best Answers 0
  • User 1
  • Popular
  • Answers
  • Editorial Team

    How to approach applying for a job at a company ...

    • 7 Answers
  • Editorial Team

    How to handle personal stress caused by utterly incompetent and ...

    • 5 Answers
  • Editorial Team

    What is a programmer’s life like?

    • 5 Answers
  • Editorial Team
    Editorial Team added an answer You've basically outlined a graph model, traditionally thought of as… May 12, 2026 at 11:38 am
  • Editorial Team
    Editorial Team added an answer I am curious why the javascript and java had different… May 12, 2026 at 11:38 am
  • Editorial Team
    Editorial Team added an answer What you should initialize the dictionary capacity to depends on… May 12, 2026 at 11:38 am

Related Questions

Greetings, I'm looking for a method to do in-line result (output) document selecting in
I have a UITableView with reorderable rows and I'm using the standard UITableViewCell.text property
I am new to vimdiff and had a question about outputting the similarities of
How do I set urlpatterns based on domain name or TLD, in Django? For

Trending Tags

analytics british company computer developers django employee employer english facebook french google interview javascript language life php programmer programs salary

Top Members

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.