What is the Difference Between the System.IO.Packaging and DocumentFormat.OpenXml.Packaging Namespaces?
(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 TOCThere 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:
https://go.microsoft.com/fwlink/?linkid=120908
You can find documentation for DocumentFormat.OpenXml.Packaging here:
https://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 =
"https://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument";
const string stylesRelationshipType =
"https://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());
}
}
}
Comments
Anonymous
December 20, 2007
There are two separate namespaces, each containing a number of classes, which you can use to open andAnonymous
December 20, 2007
Document Science CTO on Office and Open XML. My good friend Warren Wilbee recently interviewed Dr. NasserAnonymous
December 20, 2007
Document Science CTO on Office and Open XML. My good friend Warren Wilbee recently interviewed Dr. NasserAnonymous
December 21, 2007
There are two separate namespaces, each containing a number of classes, which you can use to open andAnonymous
March 26, 2008
Thanks for this Eric. I have referenced it in a email discusion of the warrants of starting a new development using only System.IO.Packaging.Anonymous
May 21, 2008
[Table of Contents] [Next Topic] Open XML Packages To follow this tutorial, you don't need to delve intoAnonymous
May 31, 2008
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 assemblyAnonymous
June 04, 2008
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 assemblyAnonymous
July 04, 2008
The Microsoft.Office.DocumentFormat.OpenXml.Packaging namespace is renamed to DocumentFormat.OpenXml.Packaging for the OpenXML SDK 1.0 download.Anonymous
July 04, 2008
Ying, you are correct. I've been lax in updating old blog posts to use the new SDK. I've corrected this one, and will take care of other posts that have the same issue.Anonymous
July 21, 2009
Is this two can be use with Framework 2.0 and II6?Anonymous
July 21, 2009
Hi Mehedi, .Net Framework 3.0 is the earliest supported version. http://msdn.microsoft.com/en-us/library/system.io.packaging.aspx -EricAnonymous
January 25, 2010
If I want to validate an uploaded excel file against an Excel template, can I use DocumentFormat.OpenXml to accomplish that?Anonymous
January 25, 2010
The comment has been removedAnonymous
January 25, 2010
Hi Eric, Before going further, seems like Open XML does not support Office 2003 document types. Is this correct? We are still in requirement phase. But I'd like to think of a potential solution in the case the client brings up this topic. Below is a possible scenario: There are defined Excel templates that clients will use to fill out (provide data). They then upload the spreadsheets to our web server and store the data in a database. The web app. has to protect the incoming data integrity by validating that it's a valid excel file (this is easy), if it follows the defined template (this is where I need more info on). The following thread is similar to what I'm asking about; but a solution is not provided there yet. http://social.msdn.microsoft.com/Forums/en-AU/architecturegeneral/thread/10719e6c-4ad6-486f-850f-af4d3f706fe7 Is it possible if you could provide a code snippet on how to examine the contents in depth? For example, check if the Excel file has a custom property named "GeneratedBy" and if it is of value "My Company".Anonymous
November 03, 2011
The comment has been removed