1

Guys, here's where I am stuck.

I have a need to create a single XPS file from a huge bunch of tiny XPS files. The problem is that I keep running out of memory when I try to do this.

I present below the code (taken from MSDN), but essentially all it does is this:

  1. It reads each tiny XPS file
  2. Extracts the pages from it.
  3. Adds these pages to a FixedDocumentSequence.
  4. When all docs are done, it writes this sequence out to the combined XPS doc.

IMO, my FixedDocumentSequence is getting too big. So, I am thinking, that maybe I can do this piece by piece - i.e. append the tiny XPS docs to the combined XPS docs one by one.

Now, I don't know how to do that. Any pointers?

Code:

            //Create new xps package
            Package combinedXPS = Package.Open(filename, FileMode.Create);
            XpsDocumentWriter xpsWriter = XpsDocument.CreateXpsDocumentWriter(new XpsDocument(combinedXPS));

            FixedDocumentSequence combinedSequence = new FixedDocumentSequence();

            //Go through each file given
            foreach (string file in filenames)
            {
                //Load Xps Package
                XpsDocument singleXPS = new XpsDocument(file, FileAccess.Read);
                FixedDocumentSequence singleSequence = singleXPS.GetFixedDocumentSequence();

                //Go through each document in the file
                foreach (DocumentReference docRef in singleSequence.References)
                {
                    FixedDocument oldDoc = docRef.GetDocument(false);
                    FixedDocument newDoc = new FixedDocument();
                    DocumentReference newDocReference = new DocumentReference();

                    newDocReference.SetDocument(newDoc);

                    //Go through each page
                    foreach (PageContent page in oldDoc.Pages)
                    {
                        PageContent newPage = new PageContent();
                        newPage.Source = page.Source;
                        (newPage as IUriContext).BaseUri = ((IUriContext)page).BaseUri;
                        newPage.GetPageRoot(true);
                        newDoc.Pages.Add(newPage);
                    }

                    //Add the document to package
                    combinedSequence.References.Add(newDocReference);
                }
                singleXPS.Close();
            }

            xpsWriter.Write(combinedSequence);
            combinedXPS.Close();
Vaibhav
  • 11,310
  • 11
  • 51
  • 70

1 Answers1

2

XPS documents are just zipped up XAML files, I bet you could just directly write out an XML from all of the source files without keeping it all in memory, then zip it up. There's even .NET APIs that help you deal with these kinds of files directly.

Ana Betts
  • 73,868
  • 16
  • 141
  • 209
  • Sadly - it's not that trivial. And yes, I am aware of the .Net API. Which is what I am using in the code I inserted. – Vaibhav Mar 16 '11 at 05:24
  • I'm referring to the .NET API for the OPC standard – Ana Betts Mar 16 '11 at 05:54
  • From your description above, it *is* that trivial. Read some XML files, append them all to a different XML file. Is your description leaving stuff out? – Ana Betts Mar 16 '11 at 05:56
  • Ah - gotcha on API on OPC - will investigate. But not sure on why you think it's just about reading some XML files. Resources from all of the smaller XPS documents will have to be merged as well, no? – Vaibhav Mar 16 '11 at 06:15
  • Paul is right, seems like all you'd have to do is iteratively a) unzip the XPS and b) pull out the XAML in .xps\Documents\n\Pages\n.fpage. Glue it all together and presto? (Untested, YMMV) – Rafael Rivera Mar 16 '11 at 06:28
  • @Vaibhav Ah you're right, it's a bit more complex than that with images, but shouldn't be too onerous – Ana Betts Mar 16 '11 at 17:03