Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Hello XPS World - Part 2 of n (of too many)

0.00/5 (No votes)
2 Aug 2008 1  
Well, somebody had to do it.

Contents

Introduction

In the first article in this series, I referred to the problems I found in finding good sources to generate XPS with - but I only covered the XPS structure in that article. So finally, here's a small taste of one way to generate XPS documents, focusing on using the API in the .NET Framework.

Background

It's been a little long coming this article, especially considering how short it is. Inspite of the fact that it's a "Hello World" application, it's not completely useless. I hope it will provide some good pointers.

At this point, I definitely should give credit to Bob Watson's article: "XPS Documents: A First Look at APIs For Creating XML Paper Specification Documents"; much of the code in this project is plagiarised from his article.

Using the Code

This is yet another simple console application. Once executed, it creates the document "HelloWorld.xps". It also makes a few assumptions, for instance, that it can find the arial.ttf font file at the location C:\Windows\Fonts. Please make the necessary changes to get it working.

First of all, what do you need to get at the XPS APIs? For that, add a reference to ReachFramework.dll. However, it effectively needs to reference WindowsBase.dll for the zip file work that it does. In other words, you'll need to reference to both DLLs. Within your code, you'll also need to add a using statement for System.Windows.Xps.Packaging.

So first off, there's cracking open a new XPS document. Here's an example:

#region The setup - Creating all the objects needed
// Create the new document
XpsDocument xd = new XpsDocument("HelloWorld.xps", FileAccess.ReadWrite);

// Create a new FixedDocumentSequence object in the document
IXpsFixedDocumentSequenceWriter xdSW = xd.AddFixedDocumentSequence();

// Ccreate a new FixedDocument object in in the document sequence
IXpsFixedDocumentWriter xdW = xdSW.AddFixedDocument();

// Add a new FixedPage to the FixedDocument
IXpsFixedPageWriter xpW = xdW.AddFixedPage();

// Add a Font to the FixedPage and get back where it ended up
string fontURI = AddFontResourceToFixedPage(xpW, "C:\\Windows\\Fonts\\Arial.ttf");

StringBuilder pageContents = new StringBuilder();
#endregion

You can plainly see the hierarchy of an XPS document in the above commands. Document -> Fixed Document Sequence -> Fixed Document -> Fixed Page. Keeping that hierarchy in mind makes it easier when manipulating XPS documents.

Next is creating the actual XPS itself. For this part, I've just built the XPS as a string. However, you can also take XAML and flatten it out; see Bob's article reference above for an example of this. Yet another way, of course, is to generate the XPS (XML), and there's plenty of ways of doing this.

#region The actual XPS markup
// Try changing the Width and Height and see what you get
pageContents.AppendLine("<FixedPage Width=\"793.76\" Height=\"1122.56\"
 xmlns=\"http://schemas.microsoft.com/xps/2005/06\" xml:lang=\"und\">");
pageContents.AppendLine("<Glyphs Fill=\"#ff000000\" FontRenderingEmSize=\"16\"
 StyleSimulations=\"None\" OriginX=\"75.68\" OriginY=\"90.56\"");
// Add the fontURI
pageContents.AppendFormat(" FontUri=\"{0}\" ", fontURI);
// HERE IT IS
pageContents.AppendLine("  UnicodeString=\"Hello XPS World!\"/>");
pageContents.AppendLine("</FixedPage>");
#endregion

It's about the briefest that I could get an XPS document. I've not bothered with the Indices attribute to keep things even simpler. You'll note that the fontURI comes from the return of the function call in the previous section.

The last part is finishing with all of the objects; by getting them to commit, we ensure that the various elements in the zip file get all completed correctly.

#region The shutdown - Commiting all of the objects
// Write the XPS markup out to the page
XmlWriter xmlWriter = xpW.XmlWriter;
xmlWriter.WriteRaw(pageContents.ToString());
            
// Commit the page
xpW.Commit();
// Close the XML writer
xmlWriter.Close();

// Commit the fixed document
xdW.Commit();
// Commite the fixed document sequence writer
xdSW.Commit();
// Commit the XPS document itself
xd.Close();
#endregion

And that's it. As suggested in the comments, do some playing around with some of the actual XPS markup and see what it generates. You may find that you need to delete the XPS between each run though (especially if something screws up). Try adding more resources, pages, and documents; also, try obfuscating the font files and see what you get. But for that, you'll need to actually look at the code to see what to do.

Other Parts

History

  • 2008-09-03: First version completed.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here