Refinement: Generating C# code from an XML Tree using Virtual Extension Methods

I’ve made great progress on this example to generate WordprocessingML documents from a template that is driven from C# that is written inside of content controls.  It took me longer than I thought it would, but I’ve been mostly on vacation this past week, so had to fit in coding around lots of other activities.  Also, there is Hofstadter’s law to take into account.

This post is the seventh in a series of blog posts on generating Open XML documents. Here is the complete list: Generating Open XML WordprocessingML Documents Blog Post Series

Along the way, I determined that I needed to refine the approach for generating C# code from an XML tree.  There were two refinements:

  • I needed to use the @”” syntax for strings (called verbatim string literals).  This handles cases such as insignificant white space that contains new lines.  My document generation example doesn’t need this functionality, but I dislike incomplete solutions.
  • I added an approach for injecting arbitrary code into the code that creates the XML tree.  I need to inject the code that the developer types into content controls into the code that creates the XML tree.  My approach is that if the transform encounters an element with the fully qualified name of {http://www.ericwhite.com/xmlcodegeneration}Literal then the text contents of that element are directly injected into the code to create the XML tree.

The following code shows what I mean.  The code creates an XML tree that contains an element with the special namespace/name:

XNamespace ewx = "http://www.ericwhite.com/xmlcodegeneration";
XDocument root = new XDocument(
    new XElement("Root",
        new XElement("Child", 123),
        new XElement(ewx + "Literal",
          @"new XElement(""Data"", 123),  // injected code" + Environment.NewLine),
        new XElement("Child", 345)));
Console.WriteLine(LtxToCode.XDocumentToCode(root));

When you run this code, it generates the following code that contains directly injected code:

new XDocument(
  new XElement("Root",
    new XElement("Child",
      new XText(@"123")
    ),
new XElement("Data", 123),  // injected code
    new XElement("Child",
      new XText(@"345")
    )
  )
)

To avoid having two versions of the code posted on my blog, I’ve altered the previous post to contain the corrected code. In the next post, I’ll discuss pros and cons of text templates.

Leave a Comment