Displaying XPS Documents in Silverlight

I’ve recently been involved on a project that has a requirement to create and view XPS documents in Silverlight.  The application needs to display the XPS file in a full screen window together with zoom and navigation features.

After a little searching on how to do this, I was able to get a head start with this great post from David Anson, which includes sample code for viewing XPS files in Silverlight 2 beta 2.  As his updated post attests to however, there were a few issues with Silverlight 2 due to a breaking change with the ways that font resources could be referenced from within a Silverlight assembly.  Fortunately, this post from Li Chen pointed me in the right direction, separating out the ODTTF fonts into separate XAP files which can be referenced at runtime. 

The sample code provided by Li Chen works well with the sample XPS files provided, but I couldn’t get it working with an XPS file generated using Microsoft Word.  After a little debugging this weekend, I found a few subtleties with how the code dealt with XPS files geneated from Microsoft Word:

Firstly, the root document of the XPS file is called FixedDoc.fdoc instead of FixedDocument.fdoc (which is the name when using the XPS Printer Driver).  This was fairly easy to correct using a simple check:

// Added to support "Save as XPS" from Microsoft Word
if (resourceInfo == null)
{
    resourceInfo = Application.GetResourceStream(_streamResourceInfo, ConvertPartName("/Documents/1/FixedDoc.fdoc"));
}

Secondly, the .fdoc file refers to pages using relative links.  Instead of the absolute link (e.g. /Documents/1/Pages/1.page), a relative link (e.g. /Page/1.page) was causing the sample to be unable to find the pages.  A small piece of code to append the full path quickly fixes this also.

// Update the page names for "Save as XPS" from Microsoft Word
List<string> _newPageNames = new List<string>();
foreach (String pageName in _pageNames)
{
    if (pageName.StartsWith("Page"))
    {
        _newPageNames.Add("/Documents/1/" + pageName);
    }
}

Finally, it looks like Word includes a page attribute called BidiLevel, which isn’t recognized by the Canvas element.  Adding an additional exclusion line into the sample code quickly fixed it.

_elementAttributesToRemove.Add("Glyphs", new List<string> { "BidiLevel" });

The result seems to work quite well, with an XPS file saved from Microsoft Word viewable within Silverlight.  

image

If you are interested in trying this yourself, I’ve posted a version of the sample code here which contains the above modifications.  To use the modified sample with your own XPS file, do the following: 

1.  Go into Microsoft Word and “Save as / XPS” to create a new XPS file.

2.  Download and compile the sample (note: only works in Visual Studio 2008). 

3.  Copy the XPS into your Visual Studio project, in the SimpleSilverlightXpsViewer_Web project. 

4.  In Windows Explorer, rename the original XPS file to a ZIP file.  Ignore the warning about changing the file extension.

5.  Open the zip file and go into the /Resources directory.  Look for font files ending in ODTTF – these are embedded font files for the XPS file and must be referenced separately in the Silverlight project.  Copy all of these ODTTF files to the SampleWordGenerated project in the solution.  Also note that the ODTTF files are dynamically named when the XPS file is generated.  This means that although you may have already imported the correct ODTTF files for previous XPS file that use the same fonts, you’ll still need to re-import the fonts again to handle a new XPS file. 

6.  Edit default.html in SimpleSilverlightXpsViewer_Web and on line 70 change the xpsDocument=SampleWordGenerated.xps to the correct name of your XPS file. 

7.  F5 to run and you should see your XPS document displayed within a Silverlight control!

There is still a bit of work to do with the sample code, which I think would be worth taking into a CodePlex project.  For example, the code should initially read the XPS root file (FixedDocSeq.fdseq) instead of looking or FixedDoc.fdoc or FixedDocument.fdoc directly.  It would also be great to figure out a better way of extracting the fonts more dynamically at runtime.  Other than that though I found this to be a good solution to display XPS files in Silverlight applications, especially useful as Silverlight doesn’t support the FlowDocument element (which is commonly used in WPF applications for creating documents and report generation).

23 thoughts on “Displaying XPS Documents in Silverlight

  1. Ola Karlsson

    Hi Simon,

    Thanks for the info, it’s really useful.
    Unfortunately I can’t open the sample code project, I think it might have to do with not having Silverlight 3 on my machine, did you create this in SL3?

    Reply
  2. http://

    Hi Simon,

    Have you find a solution to bind font without creating a silverlight font library?
    I try to create silverlight font library dynamically with CSC.exe and ResGen.exe, but it doesn’t work.

    Reply
  3. http://

    HI Simon! i tried downloading the sample, but when i open it in VS2008, i has an error. It says Unable to read the project file… then the names of all the prject in the solution.

    is there something i missed?!

    Reply
  4. http://

    @Nicolas – sorry, not had chance to work on this yet, but if you get this working, do let me know!

    Reply
  5. http://

    How come when I choose to create a xps using Microsoft XPS Document Writer from a PDF, the viewer does not work? this line returns null :

    Application.GetResourceStream(_streamResourceInfo, ConvertPartName(“/Documents/1/FixedDocument.fdoc”));

    Reply
  6. http://

    @Bjorn – change the XPS file to a ZIP file and see if you can find the document referenced. I suspect that the root document is under a different name (which should be easily fixed in the code).

    Reply
  7. http://

    I did do this and I can’t seem to find any differences between the xps provided by the example and the ones creted with the xps printer. The path to the FixedDocument.fdoc is exactly the same. Have you tried this yourself? Perhaps i’m doing something else wrong…

    Reply
  8. http://

    @Bjorn – try this: Rename the XPS to a ZIP. Extract all of the contents to a folder. ReZIP to a different filename. Rename to XPS. I’ve seen certain XPS formats have issues with the compression.

    Reply
  9. http://

    Hello Simon,

    I tried using a new xps created by me. I followed the steps you suggested ass
    –>created a xps file from MSWord (saving the doc as xps)
    –>Copied the xps to the web directory
    –>changed the extn name zip and then copied the font files from Resource to SampleWordGenerated
    –>Modified the html file
    –>renamed the zip back to xps

    When I run, it shows an error “The remote server returned an error: Not found”.

    Please suggest me if I am missing anything.

    Thnaks again

    Reply
    1. eman saker

      Hello Simon,

      I tried using a new xps created by me. I followed the steps you suggested ass
      –>created a xps file from MSWord (saving the doc as xps)
      –>Copied the xps to the web directory
      –>changed the extn name zip and then copied the font files from Resource to SampleWordGenerated
      –>Modified the html file
      –>renamed the zip back to xps

      When I run, it shows an error “The remote server returned an error: Not found”.

      Please suggest me if I am missing anything.

      Reply
  10. http://

    Hello Simon,I have found all the xps files created by “Microsoft XPS Document Writer” can not be read.
    The API GetResourceStream(StreamResourceInfo,Uri) will return null.The files i got have a little difference from what you gave,and they have a common point that the “general purpose bit flag” in zip format is set 0×08,the uncompress size and compressed size is set zero.

    I guess it relates to the xps printer’s version.
    Have you encountered such problems?

    Reply
  11. http://

    i agree with Prabhat, it is not working with me either, the only difference is that I converted DOCX to XPS programmatically.
    any help :S

    Reply
  12. sajjad ahmad

    Got this error after performing all the steps:
    The Remote server returned an error not found.

    Not succeeded in displaying in silverlight , the xps file which was created from word.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>