December, 2007

  • Eric White's Blog

    What is the Difference Between the System.IO.Packaging and DocumentFormat.OpenXml.Packaging Namespaces?

    • 16 Comments

    (October 1, 2008 - Update - Open XML SDK V2 does help in consuming the XML of the parts.  See this post for more information.) 

    This blog is inactive.
    New blog: EricWhite.com/blog

    Blog TOC
    There are two separate namespaces, each containing a number of classes, which you can use to open and get at the contents of Open XML documents.

    • System.IO.Packaging is part of the .NET Framework 3.0 and 3.5. The classes are in the WindowsBase assembly.
    • DocumentFormat.OpenXml.Packaging is in an external assembly that you can download and install. The classes are in the DocumentFormat.OpenXml assembly.

    Note that neither of the above namespaces help in any way with consuming the XML in the parts. You must still use an XML programming API, such as XmlReader, XmlDocument (or best, LINQ to XML), to consume and if necessary, produce the XML.

    To use either of the above two namespaces, you need to add a reference to the appropriate assembly.

    The OpenXmlPackaging download can be found here:

    http://go.microsoft.com/fwlink/?linkid=120908

    You can find documentation for DocumentFormat.OpenXml.Packaging here:

    http://msdn2.microsoft.com/en-us/library/bb448854.aspx

    There is a bit of confusion about which of these to use.

    System.IO.Packaging

    As detailed in Packages and Parts, packages are zip files that contain a number of parts, primarily XML, but also can contain other types of parts, such as images.

    System.IO.Packaging provides classes that allow you to get at the contents of these zip files. However, it isn’t raw zipfile access; it provides means to use the relationships to navigate from part to part. This navigation is untyped. You use strings to identify the content types, and retrieve part types that are not strongly typed.

    The following code shows how to retrieve the main document part and the style part of a WordprocessingML document using this namespace:

    using System;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.IO;
    using System.IO.Packaging;
    using System.Xml;
    using System.Xml.Linq;

    class Program
    {
        static void Main(string[] args)
        {
            const string fileName = "Test.docx";

            const string documentRelationshipType =
              "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument";
            const string stylesRelationshipType =
              "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles";

            XDocument xDoc = null;
            XDocument styleDoc = null;

            using (Package wdPackage = Package.Open(fileName, FileMode.Open, FileAccess.Read))
            {
                PackageRelationship docPackageRelationship =
                  wdPackage
                  .GetRelationshipsByType(documentRelationshipType)
                  .FirstOrDefault();
                if (docPackageRelationship != null)
                {
                    Uri documentUri =
                        PackUriHelper
                        .ResolvePartUri(
                           new Uri("/", UriKind.Relative),
                                 docPackageRelationship.TargetUri);
                    PackagePart documentPart =
                        wdPackage.GetPart(documentUri);

                    //  Load the document XML in the part into an XDocument instance.
                    xDoc = XDocument.Load(XmlReader.Create(documentPart.GetStream()));

                    //  Find the styles part. There will only be one.
                    PackageRelationship styleRelation =
                      documentPart.GetRelationshipsByType(stylesRelationshipType)
                      .FirstOrDefault();
                    if (styleRelation != null)
                    {
                        Uri styleUri = PackUriHelper.ResolvePartUri(documentUri, styleRelation.TargetUri);
                        PackagePart stylePart = wdPackage.GetPart(styleUri);

                        //  Load the style XML in the part into an XDocument instance.
                        styleDoc = XDocument.Load(XmlReader.Create(stylePart.GetStream()));
                    }
                }
            }
            Console.WriteLine("The main document part has {0} nodes.", xDoc.DescendantNodes().Count());
            Console.WriteLine("The style part has {0} nodes.", styleDoc.DescendantNodes().Count());
        }
    }

    DocumentFormat.OpenXml.Packaging

    In contrast, the classes in this namespace allow you to use strongly typed access to the contents of packages. These classes reduce the amount of code that you have to write. The following shows how to retrieve the main document part and the style part of a WordprocessingML document using this namespace. You can see that the code is significantly smaller and cleaner.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.IO;
    using System.Xml;
    using System.Xml.Linq;
    using DocumentFormat.OpenXml.Packaging;

    class Program
    {
        public static XDocument LoadXDocument(OpenXmlPart part)
        {
            XDocument xdoc;
            using (StreamReader streamReader = new StreamReader(part.GetStream()))
                xdoc = XDocument.Load(XmlReader.Create(streamReader));
            return xdoc;
        }

        static void Main(string[] args)
        {
            const string filename = "Test.docx";

            using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(filename, true))
            {
                MainDocumentPart mainPart = wordDoc.MainDocumentPart;
                StyleDefinitionsPart styleDefinitionsPart = mainPart.StyleDefinitionsPart;
                XDocument xDoc = LoadXDocument(mainPart);
                XDocument styleDoc = LoadXDocument(styleDefinitionsPart);
                Console.WriteLine("The main document part has {0} nodes.", xDoc.DescendantNodes().Count());
                Console.WriteLine("The style part has {0} nodes.", styleDoc.DescendantNodes().Count());
            }
        }
    }

     

Page 1 of 7 (7 items) 12345»
Page 1 of 1 (7 items)