Programmatic Manipulation of the Microsoft Office Open XML Formats_1_ by hcj

VIEWS: 262 PAGES: 15

									Hands-on Lab Overview

  1. Introduction

HOL224: Programmatic Manipulation of the Microsoft Office Open XML Formats
        The Microsoft Office Open XML Formats enable a multitude of scenarios for building solutions that incorporate 2007 Microsoft Office
        system documents. Based on XML and ZIP file compression technologies, the formats allow developers to access information stored
        within 2007 release documents as well as to create and edit 2007 release documents without automating the Microsoft Office
        application object models.

  2. Technologies Highlighted

                XML
                Microsoft Office Word 2007
                Microsoft Office PowerPoint 2007
                Microsoft Visual Studio 2005
                Microsoft WinFX SDK

  3. Audience

                Microsoft Office system developers

  4. Scenario

        The lab exercises are as follows:
            Introduction to Automated Manipulation of Microsoft Office Open XML Documents
            Advanced Manipulation of Microsoft Office Open XML Documents

  5. Purpose of Hands-on Lab

        The goal of this lab is to show you how you can manipulate Microsoft Office system documents using the Microsoft Office Open XML
        Formats without the 2007 release. The exercises will lead you through scenarios involving programmatically manipulating documents
        using the Microsoft Office Open XML Formats.

  6. Lab Notes

       All exercises use the new Code Snippet technology in Visual Studio 2005 to make lab code easily accessible for your convenience.
Although using the snippets may simplify completing the exercises, you have the option of typing the code listed in the lab steps for a
more realistic experience. In the code examples all code to be added by you will have an example shown in context with the added code
appearing in bold.

You can insert code snippets several different ways in Visual Studio 2005. If you are not familiar with them, the lab machine simplifies
it even further by adding the Insert Snippet command on the menu bar. Simply place the cursor where you are directed to insert the
code and click Insert Snippet. Then, navigate to the appropriate snippet as directed by the lab instructions.

For example, for the first code snippet used in Exercise 1, you should select CustomizingUI, followed by Exercise1, then Code1-
UsingStatements.




Figure 2.1. Inserting a code snippet

As a convenience if you are having problems with having the lab build properly there are snippets provided for each file that is modified
in the lab that will put them in to their final state. To use these files you would first ensure that you were viewing the code in the
Development pane and then press Ctrl-A to select all text. Then you would press the Insert Snippet button navigating to the proper lab
and exercise where you should see listed a CodeComplete-Filename where Filename would be the file you are currently viewing.

This lab will use several common terms to refer to different tool panes and sections of Visual Studio 2005. Below is a diagram of the
Visual Studio application that has the positioning of the areas called out for easy reference.
           1.   Development pane
           2.   Solution Explorer
           3.   Properties Window
           4.   Toolbox
           5.   Insert Snippet button



Hands-on Lab

Discussion Points                                                                Actions taken
Exercise 1 – Introduction to Automated Manipulation of Microsoft Office
Open XML Documents

One of the key benefits of the Microsoft Office Open XML Formats is the
unlimited potential for custom solutions. Developers can leverage any tools or
technologies on any platform capable of working with ZIP files and XML to
access and alter document contents.

For example, a server-side application can be written in Visual Studio to
programmatically generate data-rich Microsoft Office system documents by
producing files that adhere to the Microsoft Office Open XML Format
reference schemas. Developers can utilize the powerful XML class library of
the .NET Framework to work with any of the XML document parts found in
Microsoft Office Open XML Format files. Using System.Xml, developers can
locate information stored in 2007 release documents using XPath or alter it
using XSLT.

One way that developers can manipulate document parts and relationships
contained in a 2007 release document container is by using the
System.IO.Packaging namespace that is included with the Microsoft WinFX
Software Development Kit (SDK).

In this lab exercise, you will be introduced to the System.IO.Packaging
namespace found in the WinFX SDK to learn how you can programmatically
manipulate Microsoft Office Open XML Documents.

About the Style Swapper Application

In the following steps you will be developing a .NET console application that
programmatically changes the formatting styles being used in an Office Word
2007 document without using the 2007 release. The program accomplishes
this by exchanging the document’s current styles XML part with one
previously extracted from another Office Word 2007 document. The result is
that the target document adopts the “look and feel” as defined in the new
styles XML part borrowed from the other document.

Conversely, you can edit the XML within the existing styles XML part to
change a document’s styles. But swapping the entire part offers many
advantages. For example, instead of having a program write XML according
to the Microsoft Office system schema for styles, you can simply use the
2007 release to style documents and then extract the styles XML part to
reuse with other documents. This means you do not have to learn the
schema or worry about potential errors in processing the XML. Also,
swapping a single XML part is a faster process than parsing the XML
contained within an XML document part.

Although this scenario is simplified for lab purposes, imagine extending the
application to allow users to select from a collection of styles.xml parts
containing different styles that could be automatically applied to an entire
library of documents.

You are going to begin with an existing Visual Studio project, so that you will    Login using the following credentials:
not have to do some of the typical steps that are not the focus of the lab. For             a. Username: administrator
example, project references to System.Xml and the WinFX SDK have been                       b. Password: pass@word1
added in advance, as well as some common code.                                              c. Log on to: LITWAREINC
Note that the console application expects two parameters. The first is the        Wait for the Warmup Script to complete and the popup window to close.
name of the Office Word 2007 document for which you want to swap styles.          Start Microsoft Visual Studio 2005.
The second is the name of the styles document part you want to insert. The        Select File | Open Project.
SwapStylePart routine, where you will be doing most of the coding, receives       Navigate to C:\HOL\ManipulatingXmlFiles\Exercise1\StyleSwapper.
those parameters from the application’s main entry point.                         Select StyleSwapper.sln.
                                                                                  Click Open.
                                                                                  From the Visual Studio .NET Solution Explorer, right-click Program.cs.
                                                                                  Select View Code.
The Microsoft WinFX SDK includes the System.IO.Packaging namespace,               Insert code snippet ManipulatingXmlFiles > Exercise1 > Code1-Namepaces or
which simplifies working with 2007 release documents programmatically from         type the following code below the Code1-Namepaces comment.
Visual Studio .NET. With the System.IO.Packaging namespace, you can add
document parts, retrieve and update contents, or create new relationships,            // Additional project namespaces.
allowing you to build new documents or alter existing ones. Some of the               // Insert ManipulatingXmlFiles > Exercise 1 > Code1-
important members of the namespace are the Package, the PackagePart and               Namespaces
the PackageRelationship. For thorough information on the                              using System.IO;
System.IO.Packaging namespace, browse to the following URL:                           using System.IO.Packaging;
http://winfx.msdn.microsoft.com/library/en-
us/cpref/html/n_system_io_packaging.asp?frame=true

To get started with the sample application in this exercise, you need to
include the references to the System.IO.Packaging namespace and to
System.IO. Note that System.IO is included because you will be using
Stream objects to copy content into document parts.

To work with the contents of a 2007 release document, first you need to open    Insert code snippet ManipulatingXmlFiles > Exercise1 > Code2-OpenPackage
it. The System.IO.Packaging namespace has a top-level member called a            or type the following code below the Code2-OpenPackage comment in the
Package, which is synonymous with a document. Once you have opened a             SwapStylePart routine.
Package object you can inspect its structure and manipulate parts. Packages
can be opened as read only, write only or read/write, depending on your               // Open the docx container as a
needs.                                                                                System.IO.Packaging.Package.
                                                                                      // Insert ManipulatingXmlFiles > Exercise 1 > Code2-
In the next steps, you are going to add code to the SwapStylePart routine             OpenPackage (Includes Code3, Code4, Code5, Code6)
that opens the Office Word 2007 document as a package with read/write                 using (Package package = Package.Open(packagePath,
access. (The Office Word 2007 document is passed in as the variable                   FileMode.Open,
                                                                                            FileAccess.ReadWrite))
packagePath.) Notice the use of the “using” statement. Its purpose is to
                                                                                      {
automatically dispose the package once the statement has completed
                                                                                          // Set the Uri for the styles document part
execution.                                                                            (/word/styles.xml).
                                                                                          // Insert ManipulatingXmlFiles > Exercise 1 > Code3-
                                                                                      DocumentPartUri

                                                                                          // Delete the existing document part
                                                                                      (/word/styles.xml).
                                                                                             // Insert ManipulatingXmlFiles > Exercise 1 > Code4-
                                                                                         DeleteStylePart

                                                                                             // Recreate a new document part for styles
                                                                                         (/word/styles.xml).
                                                                                             // Insert ManipulatingXmlFiles > Exercise 1 > Code5-
                                                                                         CreateNewStylePart

                                                                                             // Load the new styles.xml using a stream.
                                                                                             // Insert ManipulatingXmlFiles > Exercise 1 > Code6-
                                                                                         CopyStream

                                                                                         }
To work with any part inside of the 2007 release document package, you first        Insert code snippet ManipulatingXmlFiles > Exercise1 > Code3-
need to locate it. You can reference a specific document part using its              DocumentPartUri or type the following code below the Code3-DocumentPartUri
Uniform Resource Identifier (URI), which is unique for each part. In many            comment.
cases you will know the URI for a given part because the structure of 2007
release documents is published and predictable under the Microsoft Office                // Set the Uri for the styles document part
Open XML Formats.                                                                        (/word/styles.xml).
                                                                                         // Insert ManipulatingXmlFiles > Exercise 1 > Code3-
Note that in cases where one or more similar parts may exist in a document               DocumentPartUri
(such as slides in an Office PowerPoint 2007 document or worksheets in an                Uri uriPartTarget = new Uri("/word/styles.xml",
Excel document), the use of URIs may vary from document to document. In                  UriKind.Relative);
such situations, you determine what parts and URIs are used in a document
by programmatically inspecting the relationship parts found in a package.
Relationship parts store information about each individual document part’s
relationships and include information such as part content type and URIs.
In Exercise 2, you will use relationships and content types to locate parts.
However, here in Exercise 1, the URI for the styles document part in an
Office Word 2007 document is known to be /word/styles.xml.

At the current time, the System.IO.Packaging namespace does not allow you           Insert code snippet ManipulatingXmlFiles > Exercise1 > Code4-DeleteStylePart
to copy over or replace an existing part. To swap the part, you must first           or type the following code below the Code4-DeleteStylePart comment.
remove the existing part and then create a new one using the same URI.
Note that deleting the part does not affect any of the part’s relationships. Any         // Delete the existing document part (/word/styles.xml).
relationships will remain intact and still apply to a new part created with the          // Insert ManipulatingXmlFiles > Exercise 1 > Code4-
same URI.                                                                                DeleteStylePart
                                                                                         package.DeletePart(uriPartTarget);
Further note that improper removal or creation of any document part may
cause a document to stop functioning properly within the 2007 release.

Adding a new document part to a package also requires the use of a URI. In          Insert code snippet ManipulatingXmlFiles > Exercise1 > Code5-
the case of the lab, you will simply reuse the same URI to recreate the styles       CreateNewStylePart or type the following code below Code5-
document part. One additional parameter is required when creating a                  CreateNewStylePart comment.
package, and that is the content type of the part. Current content types
already in use in a document can be found in the [Content_Types].xml part,             // Recreate a new document part for styles
located in the root of every 2007 release document package.                            (/word/styles.xml).
                                                                                       // Insert ManipulatingXmlFiles > Exercise 1 > Code5-
                                                                                       CreateNewStylePart
                                                                                       PackagePart packagePartReplacement =
                                                                                       package.CreatePart(uriPartTarget,
                                                                                                 "application/vnd.openxmlformats-
                                                                                       officedocument.wordprocessingml.styles+xml");
With the new styles part created, the final step is to copy the XML from the      Insert code snippet ManipulatingXmlFiles > Exercise1 > Code6-CopyStream or
new external styles part passed in through the stylePath variable. The             type the following code below the Code6-CopyStream comment.
System.IO.Packaging namespace does not natively handle XML as
XmlDocuments (it is actually agnostic of all content types), so the way to              // Load the new styles.xml using a stream.
copy content is through the use of streams in the .NET Framework.                       // Insert ManipulatingXmlFiles > Exercise 1 > Code6-
In the following step, you will add code that opens the external styles XML             CopyStream
document as a stream and writes it to the new styles document part. To copy             using (FileStream fileStream = new FileStream(stylePath,
the stream, you will call the routine CopyStream (already created for you –             FileMode.Open,
take a look at it) and pass in the source and destination streams.                            FileAccess.Read))
                                                                                        {
One point worth noting is that in lieu of deleting and recreating the document
                                                                                            CopyStream(fileStream,
part, you could rewrite the stream of the existing part. However, it is an
                                                                                        packagePartReplacement.GetStream());
arguably safer method to simply work with a new part.                                   }

To see the application in action, there are two style parts provided in the         Select Build | Build StyleSwapper.
Exercise 1 folder for the lab along with a sample Office Word 2007 document.        Open Windows Explorer.
To make it even easier, two .bat files were also added so you do not have to        Navigate to C:\HOL\ManipulatingXmlFiles\Exercise1.
bring up a command prompt.                                                          Double-click Sample Word Document.docx to review the document in Office
                                                                                     Word 2007.
                                                                                    Close Office Word 2007.
                                                                                    Double-click SwapFancy.bat, which applies the styles from fancy.xml.
                                                                                    Press any key to close the command console.
                                                                                    Double-click Sample Word Document.docx to review the document in Office
                                                                                     Word 2007.
                                                                                    Close Office Word 2007.
                                                                                    Double-click SwapPlain.bat, which applies the styles from plain.xml.
                                                                                    Press any key to close the command console.
                                                                                    Double-click Sample Word Document.docx to review the document in Office
                                                                                     Word 2007.
                                                                                    Close all windows and applications.

Exercise 2 – Advanced Manipulation of Microsoft Office Open XML
Documents

As mentioned earlier, the Microsoft Office Open XML Formats unlock the
potential of many document-centric, server-side application scenarios that
have long been sought after by developers. In this exercise, you will build a
Web-based application that manipulates multiple 2007 release XML
document parts and relationships to create a new Office PowerPoint 2007
.pptx document.

About the PowerPoint Presentation Generator Application

The scenario in this exercise is a common one, in which an organization
wants to allow users to produce new Office PowerPoint 2007 presentations
by using content from existing ones. In the scenario, users simply publish
existing Office PowerPoint 2007 presentations to a shared library without any
post-production processing. Then, when other users browse to the Web
application, they can select individual slides that span presentations (but still
exist in their original .pptx format) to assemble a brand new presentation
reusing the existing slides.

Behind the scenes, when the application loads it iterates all of the Office
PowerPoint 2007 .pptx files found in the specified library location. It opens
each document as a System.IO.Packaging package, allowing it to iterate
through the collection of slide XML document parts found inside. Using
XPath, the slide title is extracted from each slide part and presented to the
user in a list box on the main Web page.

Once a user has selected slides to include in the new presentation, the
application creates a new presentation document based off of a stored
template .pptx. Then, once again using System.IO.Packaging, slides parts
are copied from the library of presentation documents into the new .pptx.
Finally, the user can simply download the presentation from the server and
edit or extend it as a regular Office PowerPoint 2007 presentation.
This application is a little more complex than the one you completed in
Exercise 1, because you will need to edit the contents of existing XML parts
and create document part relationships. Also, unlike the previous application,
you will have to be able to process a variable number of document parts,
because the quantity of slides per presentation can vary. This means you
cannot assume the URIs of all the document parts as you could before.

You are going to begin with an existing Visual Studio Web application. Once            Start Microsoft Visual Studio 2005.
again, project references and some common code have been included.                     Select File | Open Project.
Note that on the initial page load, a routine called AddSlides is run. The             Navigate to C:\HOL\ManipulatingXmlFiles\Exercise2.
AddSlides routine simply loops through all the .pptx files found in the library        Select pptxGenerator.sln.
folder and calls GetSlideTitles to process each one. The GetSlideTitles                Click Open.
routine, which you will complete in a few moments, will retrieve the title text        From the Visual Studio .NET Solution Explorer, right-click Default.aspx.
from each slide found in an Office PowerPoint 2007 presentation.                       Select View Code.

As was the case in the last application you created, the System.IO.Packaging         Insert code snippet ManipulatingXmlFiles > Exercise2 > Code1-Namepaces or
namespace is central to building the application. Also, because you are going         type the following code below the Code1-Namepaces comment.
be using XML and XPath within the application, you will also need to
reference System.Xml.                                                                   // Insert ManipulatingXmlFiles > Exercise2 > Code1-
                                                                                        Namepaces
                                                                                        using System.IO;
                                                                                        using System.IO.Packaging;
                                                                                        using System.Xml;
As you saw in Exercise 1, if you know the URI to a specific document part in       Insert code snippet ManipulatingXmlFiles > Exercise2 > Code2-
a 2007 release document, you can directly access, create, or delete the part        NamespaceConstants (recommended) or type the following code below the
using the URI. That simplified finding the styles document part (styles.xml) in     Code2-NamespaceConstants comment near the top of the class definition.
the last application.
                                                                                        // Insert ManipulatingXmlFiles > Exercise2 > Code2-
However, an Office PowerPoint 2007 presentation may have multiple slides,               NamespaceConstants
which results in a .pptx container having multiple parts for the presentation           private const string documentRelationshipType =
elements, such as slides, slide notes, and slide layouts. For example, having           "http://schemas.openxmlformats.org/officeDocument/2006/r
three slides in a presentation results in three slide parts named slide1.xml,           elationships/officeDocument";
slide2.xml and slide3.xml. For this reason, you will not always know all the            private const string slideRelationshipPart =
                                                                                        "http://schemas.openxmlformats.org/package/2006/relation
URIs applicable to a given .pptx.
                                                                                        ships";
                                                                                        private const string slidePartType =
To manage situations where the number of parts may vary (or even where                  "http://schemas.openxmlformats.org/officeDocument/2006/r
URIs may have been changed), you can inspect the relationship parts found               elationships/slide";
in a package. Relationship parts contain information about the relationships            private const string namespacePowerPoint =
between document parts, including the URIs and part content types for each              "http://schemas.openxmlformats.org/presentationml/2006/3
target part in a relationship. The Packaging API allows you to return the               /main";
collection of relationships parts by content type, meaning if you know the              private const string namespaceOfficeArt =
content type of the document parts you are looking for, you can count them              "http://schemas.openxmlformats.org/drawingml/2006/3/main
and return their URIs.                                                                  ";

The 2007 release reference schemas document all of the content types for
parts found in 2007 release documents. In the next step, you are going to
add the content types for slides and the main Office PowerPoint 2007
document part (presentation.xml) as class-level variables.

The GetSlideTitles routine is called for each presentation file found in the       Insert code snippet ManipulatingXmlFiles > Exercise2 > Code3-GetSlideTitles
document library. The following code that you are going to enter in the             or type the following code below the Code3-GetSlideTitles comment in the
GetSlideTitles routine opens the .pptx document as a Package object. Then           GetSlideTitles routine.
using the GetRelationshipsByType method of the Package object, the main
document part is located using the first for each loop.                                 // Insert ManipulatingXmlFiles > Exercise2 > Code3-
                                                                                        GetSlideTitles
Note you can locate this part directly since its URI is known, but this generic         // Open the pptx container as a
method of using content types with relationships demonstrates how any part              System.IO.Packaging.Package.
could be located.                                                                       using (Package package = Package.Open(packagePath,
                                                                                        FileMode.Open, FileAccess.Read))
                                                                                        {
Then, using the relationship for the presentation.xml document part, you can
                                                                                            // Get the main document part (presentation.xml).
use the GetRelationshipsByType method once again to return a collection
                                                                                            PackagePart documentPart = null;
of all slide parts using the content type you defined in the class variable
slidePartType. With the collection of slide parts, you then iterate each one              Uri uriDocumentTarget = null;
and use an XPath query to extract each slide title, which is then placed into a           foreach (PackageRelationship relationship in
list box.                                                                             package.GetRelationshipsByType(documentRelationshipType)
                                                                                      )
It is also worthy to note how a reference to the slide in the list box is stored.         {
The text of the ListItems is the title of the slide, while the value is the path to           uriDocumentTarget =
                                                                                      PackUriHelper.ResolvePartUri(new Uri("/ppt",
the source Office PowerPoint 2007 document and the URI to the slide part for
                                                                                      UriKind.Relative), relationship.TargetUri);
access later.
                                                                                              documentPart =
                                                                                      package.GetPart(uriDocumentTarget);
                                                                                          }

                                                                                          // Iterate each slide and extract the title string.
                                                                                          PackagePart slidePart = null;
                                                                                          Uri uriSlideTarget = null;

                                                                                          // Select each slide document part
                                                                                      (slides/slide'X'.xml) via relationship with document
                                                                                      part.
                                                                                          foreach (PackageRelationship relationship in
                                                                                      documentPart.GetRelationshipsByType(slidePartType))
                                                                                          {
                                                                                              uriSlideTarget =
                                                                                      PackUriHelper.ResolvePartUri(uriDocumentTarget,
                                                                                      relationship.TargetUri);

                                                                                                 // Get the slide part from the package.
                                                                                                 slidePart = package.GetPart(uriSlideTarget);

                                                                                                 // Load slide part as Xml via a stream.
                                                                                                 Stream partStream = slidePart.GetStream();
                                                                                                 XmlDocument xdoc = new XmlDocument(nt);
                                                                                                 xdoc.Load(partStream);

                                                                                                 // Locate the slide title using XPath.
                                                                                                 // Note: Assuming the first found text is the
                                                                                      title.
                                                                                              XmlNode xNode = xdoc.SelectSingleNode("//a:t",
                                                                                      nsManager);

                                                                                                 if (xNode != null)
                                                                                                 {
                                                                                                     // Add item to the 'available slides'
                                                                                      ListBox.
                                                                                                  // Use the slide title as the Item.Text.
                                                                                                  // Use file package and slide part Uri as
                                                                                      the Item.Value.
                                                                                                          // e.g.
                                                                                          C:\\MySlides.pptx!/ppt/slides/slide1.xml
                                                                                                          listBoxAvailable.Items.Add(new
                                                                                          ListItem(xNode.InnerText, packagePath + "!" +
                                                                                          uriSlideTarget));
                                                                                                      }
                                                                                               }
                                                                                          }
Once a user has selected slides and clicked the Create button to generate a         Insert code snippet ManipulatingXmlFiles > Exercise2 > Code4-OpenPackage
new presentation, the application starts by copying an existing presentation         or type the following code below the Code4-OpenPackage comment in the
to the destination location. Alternatively, you could follow the reference           CreateButton_Click routine.
schema for Office PowerPoint 2007 documents and build an entirely brand
new .pptx from scratch by creating a package and adding parts and                        // Insert ManipulatingXmlFiles > Exercise2 > Code4-
relationships, but starting with an existing default template is easier. This is         OpenPackage, includes Code5, 6, 7, 8, and 9
done within the CreateButton_Click routine, which captures the Create                    using (Package packageDest =
button click event.                                                                      Package.Open(pptxDestinationFullPath, FileMode.Open,
                                                                                         FileAccess.ReadWrite))
To add slides to an existing presentation document, you not only have to add             {
                                                                                             // Get the main document part (presentation.xml).
the slide parts and their corresponding relationships to the package, but you
                                                                                             // Insert ManipulatingXmlFiles > Exercise2 > Code5-
also must edit the presentation.xml file to effectively add the slides to the
                                                                                         GetDocumentPart
presentation’s slide listing. This requires that you open up the document part
as XML and edit it. But first, you need to open the document as a package in                 // Load presentation.xml part as Xml via a stream.
the following step.                                                                          // Insert ManipulatingXmlFiles > Exercise2 > Code6-
                                                                                         LoadPresentationStream

                                                                                             // For every slide selected, locate and copy the
                                                                                         destination slide part into the new pptx.
                                                                                             // Insert ManipulatingXmlFiles > Exercise2 > Code7-
                                                                                         BuildSlideList, including Code8

                                                                                             // Copy the presentation.xml part back to the
                                                                                         package.
                                                                                             // Insert ManipulatingXmlFiles > Exercise2 > Code9-
                                                                                         CopyPresentation.Xml


                                                                                         }

                                                                                   Note: The rest of the exercise code resides INSIDE of the using statement.

With the package open, you can get a reference to the document’s main part          Insert code snippet ManipulatingXmlFiles > Exercise2 > Code5-
(presentation.xml) using its content type as you did earlier. Later on, you will     GetDocumentPart or type the following code below the Code5-
use the reference to retrieve the actual XML.                                        GetDocumentPart comment.

                                                                                         // Insert ManipulatingXmlFiles > Exercise2 > Code5-
                                                                                            GetDocumentPart
                                                                                            PackagePart documentPart = null;
                                                                                            Uri uriDocumentTarget = null;
                                                                                            foreach (PackageRelationship relationship in

                                                                                            packageDest.GetRelationshipsByType(documentRelationshipT
                                                                                            ype))
                                                                                            {
                                                                                                  uriDocumentTarget = PackUriHelper.ResolvePartUri(
                                                                                                       new Uri("/", UriKind.Relative),
                                                                                            relationship.TargetUri);
                                                                                                  documentPart =
                                                                                            packageDest.GetPart(uriDocumentTarget);
                                                                                            }
To edit the XML found within an XML-based document part, you need to get               Insert code snippet ManipulatingXmlFiles > Exercise2 > Code6-
the contents from the part as a stream and load it into an XmlDocument                  LoadPresentationStream or type the following code below the Code6-
object. Then, you can run XPath queries to retrieve or change data or even              LoadPresentationStream comment.
run a transformation on the entire part. To return the XmlDocument back to
the part, you also need to use a stream, which you will do later. Here, you are             // Insert ManipulatingXmlFiles > Exercise2 > Code6-
going to select the XmlNode that contains the list of slides in the                         LoadPresentationStream
presentation. Editing this will allow you to add slides to the presentation list.           Stream partStream = documentPart.GetStream();
                                                                                            XmlDocument xmlDoc = new XmlDocument(nt);
                                                                                            xmlDoc.Load(partStream);

                                                                                            // Get the slide listing XmlNode from presentation.xml.
                                                                                            XmlNode xNode =
                                                                                            xmlDoc.SelectSingleNode("/p:presentation/p:sldIdLst",
                                                                                            nsManager);
Next, you will iterate each slide selected by the user and add it to the slide list    Insert code snippet ManipulatingXmlFiles > Exercise2 > Code7-BuildSlideList or
in the presentation.xml document part. You will also build the relationships            type the following code below the Code7-BuildSlideList comment.
between the presentation.xml document part and each new slide at this time,
using the CreateRelationship method. One notable feature of the following                   // Insert ManipulatingXmlFiles > Exercise2 > Code7-
code is using a counter to generate URIs for the slides, to follow the Office               BuildSlideList, including Code8
PowerPoint 2007 file name convention (slide1.xml, slide2.xml, slide3.xml).                  for (int i = 0; i < listBoxSelected.Items.Count; i++)
Another notable feature is that Office PowerPoint 2007 uses ID numbers for                  {
slides that start at 256, so the counter is increased by that amount to create                  // Build the presentation.xml slide list to include
IDs.                                                                                        new slides.
                                                                                                // Start the slide.xml naming at 2.
                                                                                                // Note: Assumes only one slide is in base pptx
                                                                                            template.
                                                                                                int slideNum = i + 2;

                                                                                                // Add the new slide title to the list on the Web
                                                                                            page.

                                                                                            bulletedListFile.Items.Add(listBoxSelected.Items[i].Text
                                                                                            );
                                                                                               // Create the slide Uri.
                                                                                               Uri uriSlide = new Uri(@"slides/slide" +
                                                                                           slideNum.ToString() + ".xml", UriKind.Relative);

                                                                                               // Prepare package and slide part Uri variables from
                                                                                           the ListBox Item.
                                                                                               string listItemValue =
                                                                                           listBoxSelected.Items[i].Value;
                                                                                               string[] partAsArray = listItemValue.Split('!');
                                                                                               string partSourceFile = partAsArray[0];
                                                                                               string partUri = partAsArray[1];

                                                                                                Stream streamSource = null;
                                                                                                string contentType = null;

                                                                                               // Open the source pptx and copy the slide part to
                                                                                           the new pptx package.
                                                                                               // Insert ManipulatingXmlFiles > Exercise2 > Code8-
                                                                                           CopySlideParts

                                                                                           }

                                                                                     Note: Code8 resides INSIDE of the for statement in the previous snippet.

As you iterate the list of selected slides, you will retrieve the slide parts from    Insert code snippet ManipulatingXmlFiles > Exercise2 > Code8-CopySlideParts
.pptx documents in the library by opening them as packages and extracting              or type the following code below the Code8-CopySlides comment.
the slides as streams. You will then use the streams to copy the part contents
into your new presentation.                                                                // Insert ManipulatingXmlFiles > Exercise2 > Code8-
                                                                                           CopySlideParts
Note that for the lab you are only copying slides. In a more robust, real-world            using (Package packageSource =
application, you would probably also want to copy the slide note parts and                 Package.Open(partSourceFile, FileMode.Open,
slide layout parts. For the lab, you are avoiding the extra work by simply                 FileAccess.Read))
reusing the existing parts that were already in the presentation document with             {
                                                                                               // Get the source slide part.
which you began.
                                                                                               Uri uriPartSource = new Uri(partUri,
                                                                                           UriKind.Relative);
                                                                                               PackagePart partSource =
                                                                                           packageSource.GetPart(uriPartSource);
                                                                                               streamSource = partSource.GetStream();
                                                                                               contentType = partSource.ContentType;

                                                                                               // Create the new slide part in the new pptx.
                                                                                               Uri uriPartTarget =
                                                                                           PackUriHelper.ResolvePartUri(documentPart.Uri,
                                                                                           uriSlide);
                                                                                               PackagePart partDest =
                                                                                    packageDest.CreatePart(uriPartTarget, contentType, 0);
                                                                                        CopyStream(streamSource, partDest.GetStream());

                                                                                        // Create relationships for the new slide part.
                                                                                        // Note: Using existing document parts for
                                                                                    relationships, not real slide notes, layout or styles.
                                                                                        Uri uriNotes = new
                                                                                    Uri(@"../notesSlides/notesSlide1.xml",
                                                                                    UriKind.Relative);
                                                                                        partDest.CreateRelationship(uriNotes, 0,

                                                                                    @"http://schemas.microsoft.com/office/2006/relationships
                                                                                    /notesSlide", "rId3");

                                                                                        Uri uriLayout = new
                                                                                    Uri(@"../slideLayouts/slideLayout1.xml",
                                                                                    UriKind.Relative);
                                                                                        partDest.CreateRelationship(uriLayout, 0,

                                                                                    @"http://schemas.microsoft.com/office/2006/relationships
                                                                                    /slideLayout", "rId2");

                                                                                        Uri uriStyleOverride = new
                                                                                    Uri(@"../theme/themeOverride6.xml", UriKind.Relative);
                                                                                        partDest.CreateRelationship(uriStyleOverride, 0,

                                                                                    @"http://schemas.microsoft.com/office/2006/relationships
                                                                                    /themeOverride", "rId1");
                                                                                    }
Now that you have added the slides parts and their relationships, the final    Insert code snippet ManipulatingXmlFiles > Exercise2 > Code9-
task is to return the presentation.xml part back into the package. Once you     CopyPresentation.Xml or type the following code below the Code9-
reset the stream back to the beginning of the content, you will reuse the       CopyPresentation.Xml comment.
same generic CopyStream routine you used in the previous exercise.
                                                                                    // Insert ManipulatingXmlFiles > Exercise2 > Code9-
                                                                                    CopyPresentation.Xml
                                                                                    MemoryStream xmlStream = new MemoryStream();
                                                                                    xmlDoc.Save(xmlStream);
                                                                                    xmlStream.Position = 0;

                                                                                    CopyStream(xmlStream, documentPart.GetStream());
To see how the application works, run it in debug mode and assemble a          Press F5 to debug the application.
brand new Office PowerPoint 2007 presentation document.                        Select any number of slides in the Available Slides list box (press CTRL to
                                                                                multi-select).
                                                                               Click Add.
                                                                               Click Create.
                                                                               Click the NewPresentation.pptx hyperlink.
                                                                     Click Save.
                                                                     Save the file to the My Documents folder.
                                                                     In the Download complete dialog box, click Open Folder.
                                                                     Double-click NewPresentation.pptx to view the presentation in Office
                                                                      PowerPoint 2007.
                                                                     Close all windows and applications.




Conclusion

  I.   Conclusion

       By completing this lab, you have learned how to programmatically manipulate the Microsoft Office Open XML Formats. First, you
       were introduced to the System.IO.Packaging namespace of the WinFX SDK and used it to manipulate Microsoft Office Open XML
       documents. Then, you built a Web-based application that manipulates multiple 2007 release XML document parts and relationships to
       create a new Office PowerPoint 2007 .pptx document.

								
To top