Resumé

XPS Parser con XLinq

Cristian Merighi () 0,00

Ho cominciato a metter mano alle novità del .Net Framework 3.5, ed ho trovato modo di utilizzare un po' di sintassi Linq to XML per un problemino che mi incuriosiva risolvere: recuperare il testo contenuto in un documento XPS.
Questo articolo è da considerarsi obsoleto. Alcune funzionalità potrebbero non essere più disponibili e non è possibile aggiungere commenti.

Bene! Ora che ho il mio nuovo, fiammante, Visual Studio 2008 posso finalmente tuffarmi nella profondità del .Net Framework 3.x!
Da dove cominciare? Direi D/X/Linq e poi... mmh... <random mode="on">XPS documents!</random>

Che obiettivo mi pongo per questo mio esercizietto? Voglio creare un parser per packages (documenti) XPS al fine di ottenere sotto forma di stringa il testo annidato all'interno di essi.

Sicuramente sapete tutti come un file XPS null'altro sia che un file compresso contenente una precisa struttura di files e cartelle. Trattasi si files XML con aggiunta di risorse quali immagini e fonts.

Concentriamoci sugli XML e la struttura gerarchica di un file XPS: essenzialmente abbiamo una sequenza (lista) di documenti a loro volta composti da una lista di pagine. E' proprio il contenuto di queste pagina che mi interessa recuperare.

Amico C# (3.0), aiutami tu!

// among the others referenced packages
using System.Windows.Xps.Packaging;
using System.IO.Packaging;
using System.Linq;
using System.Xml;
using System.Xml.Linq;

// ...[OMITTED CODE]
string path = @"c:\MyPath\MyDoc.xps";
XpsDocument xpsDocument = new XpsDocument(path, System.IO.FileAccess.Read);

Uri packageUri = new Uri(path, UriKind.Absolute);

Package xpsPackage = PackageStore.GetPackage(packageUri)

IXpsFixedDocumentSequenceReader ixps = xpsDocument.FixedDocumentSequenceReader;

// hard-coded index!
// in this sample code I assume to have at least one document in the package
// and I do not intend to iterate through the others.
IXpsFixedDocumentReader ireader = ixps.FixedDocuments[0];
// hard-coded index (2)!
// in this sample code I assume to have at least one page in this document
// and I do not intend to iterate through the others.
Uri pageUri = ireader.FixedPages[0].Uri;
PackagePart pagePkg = xpsPackage.GetPart(pageUri);

XmlReader xread = XmlReader.Create(pagePkg.GetStream());
// XLINQ on the stage...
XDocument xdoc = XDocument.Load(xread);
xread.Close();
// Take care of page's XML default namespace!
XNamespace xmlns = "http://schemas.microsoft.com/xps/2005/06";
XName x = xmlns + "Glyphs"; // x becomes something like 
                            // {{http://schemas.microsoft.com/xps/2005/06}Glyphs}
                            // this is the C# 3.0 way to concatenate namespaces and local names
XName ox = "OriginX";
XName oy = "OriginY";
XName u = "UnicodeString";

// XLINQ query
// beware the weak sorting algorithm used in this query!
// it's basically for academic purposals!
var glyphs = from n in xdoc.Descendants(x)
             where
             n.Attribute(ox) != null && n.Attribute(oy) != null
             orderby (double)n.Attribute(ox),
                 (double)n.Attribute(oy)
             select (string)n.Attribute(u);
             // what I get is an IEnumerable of string, that's what the query yields

// finally my page content as a sole string
string content = string.Join(string.Empty, glyphs.ToArray<string>());

Bene... penso sia tutto. Al solito un articoletto spoglio di parole, ma - spero - con codice sufficiente a renderlo utile.

Take care. Bye.

Feedbacks

  • Re: XLinq XPS Parser

    JLeRogue mercoledì 1 luglio 2009 0,00

    Hi, could you link to the whole code? I've tried implementing this, but no luck. You say in the header you use 3.5, but in the body text, you say you use 3.0. Which is it? If I can get this to work, you are my hero, man. I haven't found anywhere else on the web where people are doing this.

feedback
 

Syndicate

Autore

Cristian Merighi facebook twitter google+ youtube

Ultimi articoli

Top rated

Archivio

Dove sono?

Autore

Cristian Merighi facebook twitter google+ youtube

Le mie letture

Feeds