http://www.developer.com/

Back to article

Take the Pain out of Creating Word Documents by Using C# and XML


January 23, 2009

In today's web applications, quite often you run into the need to create a Word document that user can download. The two most common ways of accomplish this is to install a copy of Word with Office Interop on the server or use a third-party library. Both of these options have significant downsides; however, there is a far simpler way to create Word Documents using XML. Because Word natively has the ability to read/write Word documents in XML, you can utilize all of the XML/XSLT tools in .NET to create them.

The first step is to create a normal Word document to be used as a template. Figure 1 shows a simple Word doc with which you will start to produce a report for Sales Territories from the Adventure Works sample database.

Figure 1: Word Document Template

Although this document does not make much sense at this point, you will use the markers in the document to help build the XSLT. To save this document to an XML file, you will need to save the file in the Word 2003 XML Document format shown in Figure 2.

Figure 2: Save as Word XML

Creating the XSLT

Now that you have an XML file, you can start the process of creating an XSLT (EXtensible Stylesheet Language Transformation). First, change the extension of the file from XML to XSLT. Then, open the XSLT in an XML editing tool. Next, you need to add a couple of tags at the top and bottom so that you can call this a XSLT. At this point, the top of the XSLT document should show the following couple of tags:

<?xml version="1.0" encoding="utf-8"?>
<w:wordDocument xmlns:aml=
   "http://schemas.microsoft.com/aml/2001/core" ...

You need to add two lines between these, as shown below:

<xsl:stylesheet version="1.0"
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">

Then, at the end of the file, you need to add the following two lines to close out those tags you added to the top:

</xsl:template>
</xsl:stylesheet>

Now, you have a very basic XSLT; however, you have not really done anything interesting with it yet. Before you go further into the XSLT, you need to take a look at the XML you are going to create to build your Word doc.

<?xml version="1.0" encoding="utf-8"?>
<doc>
   <title>The Title of my Document</title>
   <region>
      <name>Region #1</name>
      <salesdiff>$123,000</salesdiff>
      <group>
         <group>
            <groupname>Group #1</groupname>
            <salesdiff>$300</salesdiff>
         </group>
      </group>
      <group>
         <group>
            <groupname>Group #2</groupname>
            <salesdiff>$300</salesdiff>
        </group>
      </group>
   </region>
   <region>
      <group>
         <group>
            <groupname>Group #1</groupname>
            <salesdiff>$300</salesdiff>
         </group>
      </group>
      <group>
         <groupname>Group #2</groupname>
         <salesdiff>$300</salesdiff>
      </group>
   </region>
</doc>

This XML file contains two regions; within each region are two groups. Now that you have a sample XML file, you have a reference to use in adding to the XSLT. Starting with the document title, search the XSLT for the text "Document Title". Then, replace "Document Title" with <xsl:value-of select="doc/title"/>. After modifying the line in the XML, it should look the same as the following:

<w:t><xsl:value-of select="doc/title"/></w:t>

This modification inserts the Title into this position in the document. Next, you'll dig into the region and groups. A couple of lines down in the XSLT, after the line above, you should locate a line as follows:

</w:p>

After this line, add the following XSLT statement to loop through part of the document for each region.

<xsl:for-each select="doc/region">

Again, you will need to close the XSLT statement towards the end of the document. The closing statement should appear after the </w:tbl>. Now that you are at this point, it would be good to explain a couple of the tags in the XML document. If you are familiar with HTML table tags, there are some similarities, such as <w:tbl> for table, <w:tr> for table row, and <w:tc> for table cell. Next, you need to put in the tags to populate the region values within the loop. Search for the text "Region". Replace this line with the line below:

<w:t><xsl:value-of select="name"/> --
     <xsl:value-of select="salesdiff"/></w:t>

This line places the name and salesdiff values for this region. The group below region is performed using the same process of the <xsl:for-each> and <xsl:value-of> statements.

Transformation Method

Next, build the code to create the XML data and transform it using the XSLT you just created. Listed below is the method that uses all of this and creates the Word document.

private void TransformToDoc(XmlDocument doc)
{
   // XslTransform class for loading an XSLT file.
   XslCompiledTransform _transform;

   // String: Path to XSLT file.
   string _xslPath;

   // Get paths for XSLT file
   _xslPath = Server.MapPath("Template.xslt");

   string filename = "Document - " +
      DateTime.Now.ToString("MM-dd-yyyy HHmmss") + ".doc";
   Page.Response.Clear();
   Page.Response.Buffer = true;
   Page.Response.AddHeader("content-disposition",
      "attachment;filename=" + filename);
   Page.Response.ContentType = "application/x-msword";
      Page.Response.Charset = null;

   // Transform _transform = new XslCompiledTransform();
   _transform.Load(_xslPath);
   _transform.Transform(doc, null, Page.Response.OutputStream);
   Page.Response.Flush();
   Page.Response.End();
}

By using the input XMLDocument, this method transforms the XML into Word compatible XML using the XSLT you created above. This method also populates the HTTP header and Content Type information so the web browser will prompt the user to open the document with Microsoft Word. In the event that you want to save the XML document directly, it is fairly simple to remove the Page statements and change the _transform.Transform call to output to a file instead of the OutputStream.

Conclusion

At this point, you have created a very simple process to convert a Word document to an XML file, then to an XSLT file that you can use to convert XML data to a format readable by Word. This process is compatible with both Word 2003 and 2007 and works especially well with web applications; with the proper header values, Word will automatically open the file transparently to the user. Its important to note that, because this approach uses XML, it can produce files that can become quite large. However, after creating the XSLT, this is quite simple and works very well for reports without the need for third-party libraries.

Download the Code

You can download the code that accompanies the article here.

About the Author

Chris Bennett is a manager with Crowe Horwath LLP in the Indianapolis office. He can be reached at chris.bennett@crowehorwath.com.

Sitemap | Contact Us

Thanks for your registration, follow us on our social networks to keep up-to-date