a 'mooh' point

clearly an IBM drone

Værktøjer, OOXML, System.IO.Packaging

Efter en masse arbejde i de sidste måneder med OOXML i debatter rundt omkring, er turen nu kommet til et par ord om generelt at danne OOXML-filer. Microsoft har frigivet deres understøttelse af OOXML-formatet som en del af Microsoft .Net Framework 3.0 . Det er inkluderet som et nyt namespace i hierarkiet, nemlig System.IO.Packaging. Det er naturlig vis dejligt, at der nu er et helt namespace i .Net til arbejdet med OOXML-filer, men det har desværre den konsekvens, at man skal have installeret .Net 3.0 for at kunne arbejde med det. Har man ikke adgang til .Net 3.0, så skal man have adgang til 3.-parts produkter.

Det første man skal lægge mærke til er navnet på det nye namespace. Det giver nemlig en idé om tilgangsvinklen til anvendelsen af OOXML-filer. Centrum for anvendelsen er nemlig OPC - eller Open Packaging Convention. Så hvis man skulle tro, at man nu skulle til at arbejde med tekstbehandlingsdokumenter eller regneark, så bliver man skuffet. Du skal nemlig til at arbejde med pakkeformatet i OOXML - OPC. 

Nå - men vi skal jo til det

Dannelse af et tekstbehandlingsdokument

Ét af mine kritikpunkter af AODL var jo, at man "kun" kunne arbejde med filer og ikke kunne arbejde med streams. Jeg æælsker streams, så jeg har forsøgt at lave mit eksempel med OOXML som en streambaseret implementering.

[code:c#]

MemoryStream mXml = new MemoryStream();

Package package = Package.Open(<my stream>, FileMode.Create);
Uri uri = new Uri("/jlundstocholm/document.xml", UriKind.Relative);
PackagePart DocPart =
  package.CreatePart(
  uri,
  "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml");

XmlTextWriter writer = new XmlTextWriter(mXml, Encoding.Default);
writer.WriteRaw(@"<?xml version=""1.0"" encoding=""UTF-8"" standalone=""yes""?><w:document xmlns:r=""http://schemas.openxmlformats.org/officeDocument/2006/relationships"" xmlns:w=""http://schemas.openxmlformats.org/wordprocessingml/2006/main"" ><w:body><w:p><w:r><w:t>Hello World!</w:t></w:r></w:p></w:body></w:document>");
writer.Flush();
writer.Close();
byte[] document = mXml.ToArray();
mXml.Close();

using (Stream DocPartStream = DocPart.GetStream(FileMode.Open))
{
  DocPartStream.Write(document, 0, document.Length);
}

package.CreateRelationship(
  uri,
  TargetMode.Internal,
  "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
  "rID1");
package.Close();

fs.Flush();
fs.Close();

[/code]

Kodegennemgang

Det første jeg gør er at åbne et Package-objekt. I mit tilfælde er det på basis af et System.IO.Stream-objekt (my stream), men det kunne også være en simpel filreference. Da jeg skal lave et tekst-dokument tilføjer jeg en adresse på dette (Uri) og danner en PackagePart med denne reference. Hvis jeg ønskede at lave et regneark i stedet, ville det være på nøjagtigt samme måde - men sidste parameter i CreatePart()-metoden er en "ContentType", der skulle ændres til at være til regnearkstypen. Herefter putter jeg via noget stream-gymnastik mit tekstbehandlingsdokument i min PackagePart. XML'en for dette dokument er den XML jeg dannede til eksemplet om den minimale OOXML-fil. Det sidste jeg skal gøre er herefter at definere referencen til den PackagePart, der indeholder mit tekstbehandlingsdokument. Der defineres, at referencen er en intern reference (den kunne også pege ud af pakken) samt hvilken relationstype jeg gerne vil danne. Slutteligt ryddes der op i de oprettede Stream-referencer.

Konklusion 

Hele ovenstående kodeeksempel er jo gennemsyret af selve OPC-formatet - og jeg kan ikke lade være med at tænke: What the fuck? Hvorfor skal det være så svært? Her er AODL-tilgangsvinklen, der er dokument-centrisk - jo noget nemmere at kapere end dette OPC-helvede. Jeg kan godt lide muligheden for at arbejde med streams og ovenstående var sådan semi-sjov at skrive - men helt ærligt? Som udvikler er jeg ikke nødvendigvis interesseret i at kende alle de esoteriske detaljer om OOXML og dens XMl-væsen - jeg vil bare danne et dokument. Det var jo nøjagtigt den måde man tidligere dannede Office-dokumenter på via Office Automation og COM - her skulle man heller ikke vide detaljer om persisteringslogikken ... man skulle blot danne dokumenter.

Jeg har tidligere haft den opfattelse, at én af Microsofts store styrker var/er at udstyre os udviklere med lækre værktøjer, der giver os glæde ved at programmere ... udover selve opgaverne selv, naturligvis. Jeg har også indtil denne artiklel ment, at ODF ville få det svært, da ODF ikke alene skal vinde på desktoppen - det skal også vinde ved os udviklere. Jeg var sikker på, at de værktøjer Microsoft kunne komme med ville slå fx AODL med flere længder. Men det er i hvert fald ikke med denne tilgangsvinkel man vinder os "over", og jeg håber meget, at Microsoft (eller andre) frigiver nogle klasseabstraktionslag til OOXML og OPC, der giver os mulighed for at danne dokumenter som i AODL - og ikke kræver viden om, hvorden det rent faktisk persisteres. Man kan jo passende starte med at kigge i fx klasse-bibliotekerne til dannelse/afsending af emails i .Net (System.Net.Mail.MailMessage). Her er det jo ikke nødvendigt for mig at vide meget om selve mail-formatet for at kunne sende en email. Det klarer klasserne for mig. Måske man kunne blive inspireret her?

Kildekode: OPCCreator.zip (5,39 kb)

Min vurdering (af 5 max mulige smileys)

SmileSmile


Comments are closed