Welcome to MSDN Blogs Sign in | Join | Help
The OpenXmlDocument Class

This example takes the plumbing code from Packages and Parts, refactors it a bit, and creates an object graph that will be easy to query using LINQ to XML. There are a few points to note about this code:

·         To make reading the code as easy as possible, it was written in the spirit of a dynamic language, such as Python or Ruby. The Relationship class (implemented below) consists of as a set of read/write properties using the new C# 3.0 automatic properties syntax. We don’t really care that much that the properties are in some cases settable, when in fact maybe they should not be. After all, we’re going to write pure functional code that never mutates anything. Our main concern is using a syntax that is as lightweight as possible. We’ll see other examples of this approach later.

·         The OpenXmlDocument class implements IDisposable, and in its Dispose method calls the Close method on the Package. IDisposable isn’t really in the spirit of pure, stateless functional programming, but since the Package class implements IDisposable, the correct approach for the OpenXmlDocument class is to also implement IDisposable. Besides, I’m not a purist! And there are times when imperative code is easier to write (and read) than pure FP declarative code.

·         The CreateRelationshipList method contains a query that uses a PackageRelationshipCollection as its source, and projects a collection of Relationship objects. By projecting a new collection of our own type of objects, we’ll improve the readability of the code that uses this class, improve the IntelliSense experience, and provide a place to store stuff like our LINQ to XML tree (in an XDocument object).

·         To simplify accessing child relationships for a PackagePart, the Relationship class below contains a List<Relationship> property that is initialized when a PackagePart contains a PackageRelationshipCollection.

·         This code was compiled with the RTM version of Visual Studio 2008: C# 3.0 and .NET Framework 3.5.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;
using System.IO.Packaging;
 
namespace Microsoft.Examples.LtxOpenXml
{
    class Relationship
    {
        public string Id { get; set; }
        public string RelationshipType { get; set; }
        public string ContentType { get; set; }
        public System.IO.Packaging.TargetMode TargetMode { get; set; }
        public Uri SourceUri { get; set; }
        public Uri TargetUri { get; set; }
        public PackagePart PackagePart { get; set; }
        public XDocument XDocument { get; set; }
        public List<Relationship> Relationships { get; set; }
    }
 
    class OpenXmlDocument : IDisposable
    {
        // public
        public string Name { get; set; }
        public Package Package { get; set; }
        public List<Relationship> Relationships { get; set; }
 
        // private
        private bool disposed = false;
 
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
 
        private void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                    Package.Close();
                disposed = true;
            }
        }
 
        private XDocument LoadXDocument(string relationshipType,
            PackagePart part)
        {
            if (XmlContentTypes.Contains(part.ContentType))
                return XDocument.Load(XmlReader.Create(part.GetStream()));
            else
                return null;
        }
 
        private List<Relationship> CreateRelationshipList(
            PackageRelationshipCollection prc)
        {
            return (
                from pr in prc
                where pr.TargetMode == TargetMode.Internal
                let uri = PackUriHelper.ResolvePartUri(
                    new Uri(pr.SourceUri.ToString(), UriKind.Relative),
                    pr.TargetUri)
                let part = pr.Package.GetPart(uri)
                let contentType = part.ContentType
                let xdoc = LoadXDocument(pr.RelationshipType, part)
                let partRelationshipList =
                    CreateRelationshipList(part.GetRelationships())
                select new Relationship
                {
                    Id = pr.Id,
                    RelationshipType = pr.RelationshipType,
                    TargetMode = pr.TargetMode,
                    ContentType = part.ContentType,
                    SourceUri = pr.SourceUri,
                    TargetUri = pr.TargetUri,
                    PackagePart = part,
                    XDocument = xdoc,
                    Relationships = partRelationshipList
                }
            ).ToList();
        }
 
        public OpenXmlDocument(string name)
        {
            Name = name;
            Package = Package.Open(Name, FileMode.Open, FileAccess.Read);
            Relationships = CreateRelationshipList(
                Package.GetRelationships());
        }
 
        public HashSet<string> XmlContentTypes = new HashSet<string>
        {
            "application/vnd.openxmlformats-officedocument.custom-properties+xml",
            "application/vnd.openxmlformats-officedocument.customXmlProperties+xml",
            "application/vnd.openxmlformats-officedocument.drawing+xml",
            "application/vnd.openxmlformats-officedocument.drawingml.chart+xml",
            "application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml",
            "application/vnd.openxmlformats-officedocument.drawingml.diagramColors+xml",
            "application/vnd.openxmlformats-officedocument.drawingml.diagramData+xml",
            "application/vnd.openxmlformats-officedocument.drawingml.diagramLayout+xml",
            "application/vnd.openxmlformats-officedocument.drawingml.diagramStyle+xml",
            "application/vnd.openxmlformats-officedocument.extended-properties+xml",
            "application/vnd.openxmlformats-officedocument.presentationml.commentAuthors+xml",
            "application/vnd.openxmlformats-officedocument.presentationml.comments+xml",
            "application/vnd.openxmlformats-officedocument.presentationml.handoutMaster+xml",
            "application/vnd.openxmlformats-officedocument.presentationml.notesMaster+xml",
            "application/vnd.openxmlformats-officedocument.presentationml.notesSlide+xml",
            "application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml",
            "application/vnd.openxmlformats-officedocument.presentationml.presentationProperties+xml",
            "application/vnd.openxmlformats-officedocument.presentationml.slide+xml",
            "application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml",
            "application/vnd.openxmlformats-officedocument.presentationml.slideMaster+xml",
            "application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml",
            "application/vnd.openxmlformats-officedocument.presentationml.slideUpdateInfo+xml",
            "application/vnd.openxmlformats-officedocument.presentationml.tableStyles+xml",
            "application/vnd.openxmlformats-officedocument.presentationml.tags+xml",
            "application/vnd.openxmlformats-officedocument.presentationml.template.main+xml",
            "application/vnd.openxmlformats-officedocument.presentationml.viewProps+xml",
            "application/vnd.openxmlformats-officedocument.spreadsheetml.calcChain+xml",
            "application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml",
            "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml",
            "application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml",
            "application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml",
            "application/vnd.openxmlformats-officedocument.spreadsheetml.externalLink+xml",
            "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheDefinition+xml",
            "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheRecords+xml",
            "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotTable+xml",
            "application/vnd.openxmlformats-officedocument.spreadsheetml.queryTable+xml",
            "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionHeaders+xml",
            "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionLog+xml",
            "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml",
            "application/vnd.openxmlformats-officedocument.spreadsheetml.sheetMetadata+xml",
            "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml",
            "application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml",
            "application/vnd.openxmlformats-officedocument.spreadsheetml.tableSingleCells+xml",
            "application/vnd.openxmlformats-officedocument.spreadsheetml.userNames+xml",
            "application/vnd.openxmlformats-officedocument.spreadsheetml.volatileDependencies+xml",
            "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml",
            "application/vnd.openxmlformats-officedocument.theme+xml",
            "application/vnd.openxmlformats-officedocument.themeOverride+xml",
            "application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml",
            "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml",
            "application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml",
            "application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml",
            "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml",
            "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml",
            "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml",
            "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml",
            "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml",
            "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml",
            "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml",
            "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml",
            "application/vnd.openxmlformats-package.core-properties+xml",
            "application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml",
            "application/xml"
        };
    }
}

Posted: Tuesday, December 11, 2007 5:27 AM by EricWhite
Filed under: ,

Comments

Eric White's Blog said:

I have news! I am leaving my current job documenting XML technologies (primarily LINQ to XML), and taking

# December 11, 2007 1:55 AM

Eric White's Blog said:

Given my focus on LINQ to XML over the last couple of years, I have to say that LINQ to XML and Open

# December 11, 2007 2:04 AM

D.K. said:

Theseresourceisforpreparingtheproject,supervisedbyMONOandGOOGLESUMMERCODE2008,Converti...

# March 31, 2008 9:17 AM

cnblogs.com said:

These resource is for preparing the project ,supervised by MONO and GOOGLE SUMMER CODE 2008,Converting

# March 31, 2008 9:19 AM

Sonia said:

Hi,

I need ur help. I am unable to dispose XDocument . My requirement is very simple, simple reading and writing to xml file using xdocument.

pls provide your inputs to how to proceed.

# May 14, 2008 6:33 AM

EricWhite said:

XDocument doesn't implement IDisposable.  Take a look at the documentation.  This topic shows how to load an XDocument from a file:

http://msdn.microsoft.com/en-us/library/bb343181.aspx

This topic shows how to save it back to a file:

http://msdn.microsoft.com/en-us/library/bb345830.aspx

Also, take a look at the LINQ to XML Programming Guide:

http://msdn.microsoft.com/en-us/library/bb387087.aspx

# May 14, 2008 9:28 AM

Sonia said:

Many a Thanks for ur reply.

My issue is i have to keep writing xml file through web application, so it wil b written by as many users.

If i don;t close or dispose, it says, it is being used by other process.

# May 15, 2008 1:49 AM

247Blogging said:

This example takes the plumbing code from Packages and Parts , refactors it a bit, and creates an object graph that will be easy to query using LINQ to XML. There are a few points to note about this code: &#183; To make reading the code as easy as possible

# May 19, 2008 8:53 PM
Leave a Comment

(required) 

(required) 

(optional)

(required) 

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Page view tracker