Overwrite Custom XML Part in Office 2007 file

Julie Kremer (everyone should know her) had a great post in March about how to overwrite a custom XML part in an Office 2007 file in the Office Open XML format. Her sample is great. She provided it in C#, so I converted it to VB.NET for those of you who prefer that language. Here's the code:

        Dim xmlDocRelType As String = _

        "https://schemas.openxmlformats.org/officeDocument/" _

        & "2006/relationships/customXml"

        Dim officeDocRelType As String = _

        "https://schemas.openxmlformats.org/" _

        & "officeDocument/2006/relationships/officeDocument"

        Dim xmlPart As PackagePart

        Dim documentPart As PackagePart

        Dim documentUri As Uri

        Dim xmlUri As Uri

        Dim relationship As PackageRelationship

        Dim docPath As String = "C:\Memo3.zip"

        Using officePackage As Package = Package.Open(docPath, _

        FileMode.Open, FileAccess.ReadWrite)

            For Each relationship In officePackage. _

            GetRelationshipsByType(officeDocRelType)

                documentUri = PackUriHelper.ResolvePartUri( _

                New Uri("/", UriKind.Relative), _

                  relationship.TargetUri)

                documentPart = officePackage.GetPart(documentUri)

                Exit For

   Next

            For Each relationship In documentPart. _

            GetRelationshipsByType(xmlDocRelType)

                xmlUri = PackUriHelper.ResolvePartUri( _

                New Uri("/", UriKind.Relative), _

               relationship.TargetUri)

               Exit For

         Next

            xmlPart = officePackage.GetPart(xmlUri)

            Dim outputStream As Stream = xmlPart.GetStream( _

            FileMode.Create, FileAccess.ReadWrite)

            Dim ts As StreamWriter = New StreamWriter(outputStream)

            Dim xmlDoc As New XmlDocument()

            xmlDoc.Load("C:\item2.xml")

            ts.Write(xmlDoc.OuterXml)

            ts.Write(xmlDoc)

            ts.Flush()

            ts.Close()

            officePackage.Close()

        End Using

What is exactly going on? Well, here's the basic narrative: First, the code opens a Word file stored with a .zip extension (the extension doesn't really matter here). Then, it looks for the main document part. That's what the first loop is doing. Once it finds that, it looks for the customXML part. That's what the second loop is doing. From there, it gets a Stream for the custom XML part. It then loads an XML document that contains the new XML we want to pump into the custom XML part of the file. It flushes it to the stream and close the file.

Obviously, you can target a different part in the file with just a couple of simple modifications.

Big thanks to Julie for doing the experimentation here.

  Rock Thought for the Day: I bought SPIN magazine because it contained an article about the Red Hot Chili Peppers and their new album, Stadium Arcadium. I am very eager to get my hands on this double CD effort. Thankfully, they are releasing them both together rather than the annoying practice of separate releases as System of a Down did. I'll review the RHCP albums when they arrive. Also, I bought another Brad Paisley CD, and I'll review that one, too.