Office Open XML File Formats - Word 2007

In this article we will explore the Office Open XML File Formats and see how to create a simple word document using Console Application using C#.

With release of Microsoft Office System 2007, Microsoft introduced the use of Office Open XML file formats. These Office Open XML file formats allows to create or generate Office Word 2007 and Office Excel 2007 files on the web server without physical installation of a Office Word or Excel desktop applications. In this article we will also explore how these Open XML file formats are useful in developing custom application for Windows SharePoint Services and Microsoft Office SharePoint Servers.

In 2006 ECMA International approved Office Open XML file format specification as the ECMA 376 standard and was under review by the ISO international standards body at press time. As a goal of this article, we will explore these file formats to familiar you up and make you familiar with programming model required to create simple Word documents in the WSS solution.

With the use of old binary file formats of Office applications, it was too much difficult and challenging to write and deploy applications that could read, modify and generate those documents with respect to service-side execution. Introduced in 1997, the binary file formats for Word, Excel and PowerPoint and those were used till Microsoft Office 2003 editions. These binary file formats are too difficult and too tricky for most of the developers to work with directly because a little code mistake in generating or modifying Office document typically damages entire file. So to avoid this type of mistakes most of the developers have to be dependent on their own object model of Office 2003 editions or earlier versions.

The object model of the applications such as Word or Excel gives better performance on desktop rather than server when used in custom applications and components. So these types of applications are never developed and designed to be run on server side. In the server side scenarios, the applications can read and write without use of hosting applications’ object model use and this is much more difficult to achieve. But, in Microsoft Office 2000 and Microsoft Office 2003 editions, the introduction for using XML to create the document part. This has also advanced the capability of writing the portions of document using .NET Framework in some context.

But, with the release of Microsoft Office 2007, Microsoft has adopted total and complete use of the Office Open XML file formats for documents created by Word and Excel and PowerPoint. And these Office Open XML file formats are considered as blessings for WSS and MOSS developers as, these file formats do not require the installation of Microsoft Office Applications on the web hosting servers, where they need to create these documents using code and make them downloadable for the end user.

Now, we will explore the internal details and parts of Microsoft Office 2007 Word documents.

Internals of Microsoft Word 2007 documents

We will start this section by looking at the structure of a simple Word document based on the Office Open XML file format. This Office Open XML file formats are nothing but a standard ZIP file and based on standard ZIP file technology. Just its file extension is changed so we don't realize that they are ZIP files. Each file at the top-level is saved as ZIP archive. This means that we can open a Word or Excel document just same as standard ZIP file and can dive into details of that file using the ZIP file support provided in Windows or any other ZIP utility tool.

Also, we all know that with the release of Microsoft Office 2007, Microsoft has changed the file extensions for the Office suit of applications, such as Word, Excel and PowerPoint. The new file extension for Word is .docx, Excel is .xlsx and so on. Here the extra 'x' indicates that these files are based on Office Open XML file formats. Also, they continued to support the old binary file formats which are much more familiar to most people like .doc, .xls.

After installation of Word 2007 on machine, we can create a new Word document and can add text whatever we want. For our example, create a new Word document and write some sample text like, copy text from this article and paste in it and save it as MyArticle.docx. Now close the Word application, as if this is kept open we can't rename our saved file that we are going to do next. Now, navigate to the location where you have saved the MyArticle.docx file using Windows Explorer. Now, rename it to MyArticle.zip. Renaming the file to ZIP, makes the Windows Explorer to recognize the file as a standard ZIP archive. Now, we can open that ZIP file and can see the structure of folders and files that Word created.



As shown in the above image, we can see that there are most of xml files are there structured in different folders. Now, we will see some basic terminology and concepts used to configure documents in Office Open XML file formats. The top-level file means MyArticle.docx is known as a package. As this package is used as a standard ZIP archive, it automatically provides compression. This also makes the contents directly accessible to many other existing utilities and APIs on Windows and non-Windows platforms in the same way.

In the package there are two types of internal components: 1. Parts and 2. Items. Generally, parts are housing the content and items house the metadata means data about the parts. These items are further divided into relationship items and content-type items.

A part is the internal component housing content that is persisted inside the package. As we can see that most of the files are simple text files serialized as XML with an associated XML schema. Also, these parts can also be serialized as binary data when storing images or media files in Word document.

A part is identified by the name of uniform resource identifier (URI) type which contains the relative path in the package file combined with the part file name. For example, the main part in the package for a Word document is named /word/document.xml. The following list of xml files are some more examples for the parts stored in the package file.

/word/fontTable.xml
/word/settings.xml
/word/styles.xml
/stylesWithEffects.xml
/webSettings.xml
/docProps/app.xml
/docProps/core.xml

To define the relations between a source and a target parts, Office Open XML file formats use relationships. The package relationship defines an association between the top-level package and a part. A part relationship defines an association between a parent part and a child part.

These relationships are very important because they don't concern about the content of part. Relationships are independent of content-specific schemas and so, they are faster to resolve. Other benefit is that without modifying the parts we can create a relationship between them.

Relationships are housed in internal components known as relationship items. A relationship item is stored in the package same as a part, but they are not considered as part. For consistency, these relationship items are always stored in folders named _rels.

As for our example, the MyArticle.zip file contains exactly one package relationship item named /_rels/.rels. This relationship item contains XML elements to define package relationships, such as the relation between top-level package for the .docx file and the internal part /word/document.xml file.

<?xml version="1.0" encoding="utf-8" ?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
  <Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"
                 
Target="word/document.xml" Id="rId1" />
</Relationships>

As we can see in the above listing, a Relationship element contains a name, type and target path. Also, the type name for a relationship is defined by using the same conventions used to create XML namespaces. a package can also contain one or more part relationship items. For example, you should define relationships between /word/document.xml and child parts inside a package relationship item located at the URI /word/_rels/document.xml.rels. Here note that the Target attribute for a relationship in a part relationship item is a URI relative to the parent part not to the top-level package.

Each part in the package is considered and defined as specific content type. A content type in the package is metadata that defines a part's media type, a subtype and a set of optional parameters. Any content type used in a package must be defined inside a component named as content type item. Each and every package has exactly one content type item named /[Content_Types].xml. The following listing shows the content of /[Content_Types].xml file of a typical Word document.

<?xml version="1.0" encoding="utf-8" ?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
  <Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml" />
  <Default Extension="xml" ContentType="application/xml" />
  <Default Extension="jpeg" ContentType="image/jpeg" />
  <Override PartName="/word/document.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml" />
  <Override PartName="/word/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml" />
  <Override PartName="/word/stylesWithEffects.xml" ContentType="application/vnd.ms-word.stylesWithEffects+xml" />
  <Override PartName="/word/settings.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml" />
  <Override PartName="/word/webSettings.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml" />
  <Override PartName="/word/fontTable.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml" />
  <Override PartName="/word/theme/theme1.xml" ContentType="application/vnd.openxmlformats-officedocument.theme+xml" />
  <Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml" />
  <Override PartName="/docProps/app.xml" ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml" />
</Types>

Content types are used for interpretation for how to read and render the content of parts. As you can see the default content type is associated with a file extension, such as .rels or .xml. The Override elements in the above listing are generally used to define a specific part as content type that differs from the default content type associated with its file extension. For example, /word/document.xml is associated with an Overried content type that differs from the default content type used for files with an .xml extension.

Create First.docx file programmatically

The .NET Framework 3.0 is powered with new packaging APIs, which are part of WindowsBase.dll assembly. This packaging APIs are aware of the Office Open XML file formats, they are easy and handy component to manage Office Open XML files. For example, certain convenience methods make it easy to add relationship elements to a relationship item and add content type elements to a content type item. Also, packaging APIs allows the management of things without touching relationship or content type items directly.

To start programming against the packaging APIs in Visual Studio 2008, we need to add the reference to the WindowsBase assembly. Let us begin by creating a simple console application that generates a .docx file using the Office Open XML file formats. The classes that used for packaging API are conteined in the System.IO.Package namespace. See the following code listing that shows the creating of a blank package.

using System;
using System.IO;
using System.Xml;
using System.IO.Packaging;

namespace FirstDocx
{
    public class Program
    {
         public static void Main(string[] args)
        {
            Package package = Package.Open(@"C:\First.docx", FileMode.Create, FileAccess.ReadWrite);                      
            package.Close();
        }
    }
}

As per the above listing the we have used Package class's static method Open to create a new package. We can also use the same for opening the existing packages as well. This Package class is housed inside the System.IO.Package namespace. As this is the IO operation class same like other IO classes, this also need to be closed after working to release the related resources or related file. Now, our blank package is created. Once this is done, our next step is to create one or more parts and serialize content into them. For our example, we will create a single part named /word/document.xml. We can create a part by calling the CreatePart method on an open Package object and passing URI and a string-based content type as parameters.

Uri uri = new Uri("/word/document.xml", UriKind.Relative);
string partContentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml";
PackagePart documentPart = package.CreatePart(uri, partContentType);
StreamWriter streamPartWriter = new StreamWriter(documentPart.GetStream(FileMode.Create, FileAccess.Write));

As we can see from above listing, CreatePart method of Package class is used to create the document part. This method is provided with type parameters: URI based on the path /word/document.xml and the content type which is required by Office Open XML file formats for the part in a word processing document. Once the part is created, it needs to be serialized with content by using same traditional stream-based programming techniques. As per example, for this we have created a StreamWriter object by initialized by calling the GetStream method and passing that as parameter.

The StreamWriter object is used to serialize the "My first Word 2007 document" into document.xml. However, we need to see what the resulting XML is looking. See the following XML listing that represents the serialized document.xml.

<?xml version="1.0" encoding="utf-8"?>
<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
  <w:body>
    <w:p>
      <w:r>
        <w:t>My first Word 2007 document</w:t>
      </w:r>
    </w:p>
  </w:body>
</w:document>

Note that all the XML documents are defined within the http://schemas.openxmlformats.org/wordprocessingml/2006/main" namespace as per the Office Open XML file formats specifications. The XML document contains the top level document element, housing the body element that contains the main content of Word document. In the bode element there is a <p> element representing paragraph. Within the <p> element, there is a <r> element that defines a run. A run is a region of elements that share the same set of characteristics. Within each run is a <t> element that defines a range of text. So, it is now time to generate this XML segment for document with code by using the XmlWrite class from System.Xml namespace. See the following code listing.

Uri uri = new Uri("/word/document.xml", UriKind.Relative);
            string partContentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml";
            PackagePart documentPart = package.CreatePart(uri, partContentType);
            StreamWriter streamPartWriter = new StreamWriter(documentPart.GetStream(FileMode.Create, FileAccess.Write));

            string namespaceWP = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
            XmlWriter writer = XmlWriter.Create(streamPartWriter);
             writer.WriteStartDocument();
             writer.WriteStartElement("w", "document", namespaceWP);
             writer.WriteStartElement("body", namespaceWP);
             writer.WriteStartElement("p", namespaceWP);
             writer.WriteStartElement("r", namespaceWP);
             writer.WriteStartElement("t", namespaceWP);
             writer.WriteValue("My first Word 2007 document");
            writer.WriteEndElement(); //close t
            writer.WriteEndElement(); //close r
            writer.WriteEndElement(); //close p
            writer.WriteEndElement(); //close body
            writer.WriteEndDocument();
            writer.Close();
          

At this stage we have finished with XML content into document.xml. Now we need to create a relationship between the package and document.xml by using the CreateRelationship method of the Package object. This is very easy process as shown in the below listing.

//create the relationship part
            string relationshipType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument";
            package.CreateRelationship(uri, TargetMode.Internal, relationshipType, "relshipId1");
            package.Flush();

As you can see we have used Flush method after the call to CreateRelationship. This forces the packaging API to update the package relationship item with the proper relationship element. And then call to Close method closes the package and releases the handle to MyFirst.docx file.

Till now we have discussed all the necessary steps to generate a simple .docx file from the console application developed with C#.

Closer Look at Relationships

The structure of package is mostly dependent on relationships in Office Open XML file formats. If parts are created for the document, but not associated them to the package through relationships, then the applications (such as Word) which consumes the file are not able to parse them because every part must have a relationship or a chain of relationships that associate it with its parent package. As discussed, package relationships define an association of package to its top-level parts. Part relationships define a parent-child relationship between two parts within the same package. The part /word/document.xml has relationships to several different child parts, such as /word/settings.xml and /word/styles.xml.

As per specifications for Office Open XML file formats, each and every part inside a package must be related to the package itself directly or indirectly. A part, such as /word/document.xml, is directly related to the package through a package relationship. Another part, such as /word/styles.xml, is associated with the package indirectly by relation with top-level part /word/document.xml.

A very important thing to remember is that a consumer application must be able to discover any part within a package by enumerating through its relationships. As well, your own written applications must also read packages created by other applications, such as Word 2007 and Excel 2007, to discover the existing parts by enumerating relationships.

Package Viewer Application

As per Office Open XML file formats specifications, all parts housed inside a package must be discoverable through relationships. Therefore, it's possible to write down an application that inspects a package and displays all of the parts inside it. This package viewer application allows the user to select a package file by using the standard Open File dialog box. Once the user selects a file the application enumerates through all of the package relationships to find the top-level parts. I'll not discuss each and every line of the code of the application. Please download the application to see the full source code of this application.

private void openToolStripMenuItem_Click(object sender, EventArgs e) {
       // get the fileName
      if (OpenFileDialog.ShowDialog() == DialogResult.OK) {
         // store the file name
        m_fileName = OpenFileDialog.FileName;

        // create the package node
        TreeNode node = CreatePackageNode(m_fileName);

        // clear the node list and add the new one
        PackageView.Nodes.Clear();
        PackageView.Nodes.Add(node);

        // create the items under the root node, then expand it
        BuildRelationships(node);
        node.Expand();
      }
    }

The above code listing shows how the Office Open XML file is opened to discover its parts. The method CreatePackageNode creates the top-level node.

private void BuildRelationships(TreeNode expandedNode) {
       // open the package
      using (Package package = Package.Open(m_fileName)) {
        // get the relationships for the node                 
        PackageRelationshipCollection relationships = GetRelationshipsForNode(package, expandedNode);

        // add a node for each relationshipType
        SortedList<string, TreeNode> nodes = new SortedList<string, TreeNode>();
        foreach (PackageRelationship relationship in relationships) {
          TreeNode node = null;
          if (relationship.TargetMode == TargetMode.External)
            node = CreateExternalNode(relationship);
           else
            node = CreatePackagePartNode(package, relationship);

           // add the node to the sorted list
          nodes.Add(node.Text, node);
        }

        // add the nodes to the parent node
        foreach (KeyValuePair<string, TreeNode> node in nodes)
          expandedNode.Nodes.Add(node.Value);
      }
    }

The above method BuildRelationshps, opens the file using Packaging API and then travers through each relationship and builds the tree view with each parts. Please download the full source code and run the application and see how it works. The application also provides the functionality to display the contents of any XML-based parts within the package by reopening the package and getting stream-based access to target part content. This content is written to a temporary file and then is loaded into the Windows Forms WebBrowser control, which displays the XML content with color coding and collapsible sections.

private void DisplayPackagePart(Uri partUri) {
      // get the temp filename
      string fileName = Path.ChangeExtension(Path.GetTempFileName(),
          Path.GetExtension(partUri.OriginalString));
      using (FileStream stream = File.Create(fileName)) {
        // open the package
        using (Package package = Package.Open(m_fileName)) {
          // copy the data from the package part to the file
          PackagePart part = package.GetPart(partUri);
           using (BufferedStream partStream = new BufferedStream(part.GetStream())) {
            int data = partStream.ReadByte();
             while (data != -1) {
              stream.WriteByte((byte)data);
              data = partStream.ReadByte();
             }
           }
        }
       }

      // setup the browser window
      PackagePartPreview.Visible = true;
      PackagePartPreview.Navigate("file://" + fileName);
    }

The above code listing demonstrates how the package part file is saved to local disk for temporary use and displayed in the WebBrowser control.

Binding Data to Word Content Controls

We end up the articel with look at one more technique provided by Microsoft Word 2007. Here we will discuss two new features of Word 2007 that could be used when working with documents stored in the new Office Open XML file formats. The first one is the XML Data Store, which allows the user to embed  one or more user-defined XML documents as parts inside a .docx file. The other feature is Content Controls, which are user interface control defined inside the /word/document.xml part that support data entry and data binding.

To work with and to explore the Content Controls feature of Word 2007, you first need to have a Developer Tab in the Top Ribbon Bar. If you don't have then from the option dialog enable Developer Tab.

Below image shows the developer Tab and the set of controls that can be used and added to word document.



Remember that you can add Content Controls to only Word documents that are stored in the new .docx file format. As, these Content Controls can not be defined using binary format, they can't be used with older Word versions, such as Word 2003, Word 2000. These Content Controls are added to a Word document as user input elements. For example, you can create a Word document that solicits the user for certain pieces of information to complete a business document.



Content Controls have two different modes: edit mode and display mode. Edit mode enables the user to do things like enter text, select a date from a date picker or select an item from the drop-down list. Display mode is optimized for displaying and printing. The editing facility is disabled for a user who is no longer in edit mode.

Separate Data From Presentation in Microsoft Word 2007

Though the XML Data Store and Content Controls are two separate and independent features of Word 2007, they provide a powerful functionality when used together. For example, we can embed XML document customer data or an invoice inside a Word document. Then can bind Content Controls to data inside this XML document by using XPath experssions.

So, for out example, open the TestTemplate.docx file, provided with the example download. We will use the following XML document to bind the data to the content controls in our template.

<?xml version="1.0" encoding="utf-8"?>
<TestLetter xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
             
xmlns="http://testletter.com/2010/letters">
  <Customer>
    <FirstName>Jatin</FirstName>
    <LastName>Prajapati</LastName>
    <Company>My Software Solutions Pvt. Ltd.</Company>
    <Address>Outsite Baroda City, Nr. Wild Jungle</Address>
    <City>Vadodara</City>
    <State>Gujarat</State>
    <Zip>3900005</Zip>
  </Customer>
  <Date>December 01, 2025</Date>
  <Body>We miss you. Please give us a call</Body>
  <Employee>
    <Name>Jaimin Thakar</Name>
  </Employee>
</TestLetter>

Use of this technique involves manual efforts for manipulating the contents of the .docx file that you needed to use as the template. So, change the file extension from .docx to .zip of the downloaded file so that you can open the package file directly and can add parts by dragging them into the package by using Windows Explorer.

Save the above XML listing as part inside the TestTemplate.docx file using the URI /customXml/item1.xml. Note that you can use any type of name for the xml file instead of item1.xml. But for consistency with names that Word 2007 uses, we name it as item1.xml.

The next step is that we need to write something that makes the consumer application to identify this new added customer XML document. For this we will define a datastoreItem with an identifying GUID, which is accomplished by creating a part named /customXml/ItemProps1.xml file. The content of this file looks like below one:

<?xml version="1.0" encoding="utf-8"?>
<ds:datastoreItem ds:itemID="{040EE649-ADA8-45ca-B701-C88E40CB3DD6}"
                    
xmlns:ds="http://schemas.openxmlformats.org/officeDocument/2006/customXml">
  <ds:schemaRefs>
    <ds:schemaRef ds:uri="http://www.w3.org/2001/XMLSchema" />
    <ds:schemaRef ds:uri="http://testletter.com/2010/letters" />
  </ds:schemaRefs>
</ds:datastoreItem>

Now, the next step is to create a part relationship between /word/document.xml and /customXml/item1.xml. The relationship should define the parent part as /word/document.xml and child part as /customXml/item1.xmls and the relationship is created using the following string:

http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXml

After this completed, we can directly fetch the data from datastoreitem from /word/document.xml. Now we will bind this datastoreItem to out template content controls. Unfortunately, Word 2007 has no any user interface to bind the Content Controls with XML Data Store enbedded in the file. So, we need to do this manually using Visual Studio 2008 or any other text editor you are comfortable with. See the following XML listing:

<?xml version="1.0" encoding="utf-8"?>
<w:stdPr>
  <w:dataBinding w:prefixMappings="xmlns:ns0='http://testletter.com/2010/letters'"
                
w:xpath="/ns0:TestLetter[1]/ns0:Customer[1]/ns0:FirstName"
                
w:storeItemID="{040EE649-ADA8-45ca-B701-C88E40CB3DD6}" />
</w:stdPr>

In the above listing, the data binding element contains the GUID of storeItem that references the GUID of the datastoreItem that contains the customer data. This also has xpath attribute that defines an XPath expression to bind the Content Control to a specific element within the user-defined XML file. Once you have updated the /word/document.xml file to contain all the data boudn Content Control elements you can use this to see how it works.

Summary
In this article, we explored the Office Open XML file format and its internal components. Also we discussed how to create a Word document programmatically. Hope this will help you for your development scenarios.

Download the sample application from here.

By Jatin Prajapati   Popularity  (7693 Views)