Transfromácia formulára do HTML z kódu formulára

Publikoval Michal Kočí dňa 2.6.2007 o 03:42 v kategórii InfoPath

Toto je asi nadlho jeden z posledných príspevkov o InfoPath formulároch, nakoľko som už na inom projekte a na formolároch tak naďalej nepracujem. Napriek tomu, toto je jedna z úloh, ktorá bola docela "tricky" - požiadavka bola, aby na formulári bolo tlačidlo, ktoré odošle do webovej služby HTML podobu seba samého. T.j. trebalo prinútiť formulár, aby sa pretransformoval do HTML podoby a túto podobu niekam odoslal. Odoslanie binárnych dát nie je problém, ale ako vygenerovať HTML podobu seba samého...

Celé riešenie je vo finále jednoduché, pokiaľ máme dostatočné vedomosti o tom, čo to vlastne InfoPath formulár je. Takže, InfoPath formulár je vlastne formulár, ktorý pracuje s dátami v dátovom zdroji a tieto dáta alebo od užívateľa zbiera, alebo mu ich reprezentuje. Interne pracuje s XML dokumentom, ktorý obsahuje samotné dáta a na prezentáciu používa transformáciu do HTML.

Samotný súbor InfoPath formulára, teda ten s príponou XSN je vlastne CAB archív, ktorý obsahuje niekoľko rôznych súborov rôzneho druhu. Ak si teda premenujete súbor a zmeníte mu príponu na CAB, otvoríte takýto súbor napríklad vo WinRARe alebo v Total Commanderovi. Môžete potom detailnejšie preskúmať štruktúru súboru a zistíte, že v zásade formulát obsahuje:

  • Manifest ktorý popisuje obsah súboru (manifest.xsf)
  • Schémy dátových zdrojov (*.xsd)
  • XSL transformácie pre jednotlivé pohľady (view) (*.xsl)
  • Referencované assembly (*.dll)
  • Použité obrázky (*.jpg, *.gif, …)

Takže, keď už vieme, že formulár na reprezentáciu údajov používa transformáciu dátového zdroja do HTML a vieme, že transformácie sú súčasťou dokumentu, jediné čo potrebujeme je prístup k dátam, prístup k transformáciám - potom môžeme transformáciu vykonať kedykoľvek.

V mojom prípade som vždy chcel transformovať defaultný pohľad (pomenovaný View 1), ktorému vždy prísluší transformačný súbor view1.xsl. Jediný problém teda je, ako z kódu spúšťaného vo formulári získať túto transformáciu. Odpoveďou je veľmi zle dokumentovaná (skôr by som to nazval nedokumentovaná) metóda OpenFileFromPackage ktorú obsahuje objekt Template (ktorý je typu FormTemplate). Tej stačí predať názov súboru a výsledkom je Stream s ktorým môžete ďalej pracovať.

Takže, ak vopred nepoznáte názov súboru, mali by ste si najskôr vypýtať manifest.xsf, v ňom si vyhľadať súbor ktorý potrebujete a potom si vypýtať aj ten. Ako som spomenul, v mojom prípade sa súbor vždy volá view1.xsl, takže o problém menej. Síce som už raz popisoval Ako transformovať XML dokument XSL transformáciou, ale:

  • Opakovanie je matka múdrosti
  • Niektoré triedy (alebo to boli metódy?) z popísaného riešenia sú obsolete
  • Najlepšie si ukázať celý príklad

No, poďme na to poporiadku. Potrebujeme Stream s transormáciou:

private Stream GetViewStream()
{
    return Template.OpenFileFromPackage("view1.xsl");
}

Potrebujeme dáta, tiež ako Stream:

private Stream GetDataStream()
{
    XPathNavigator data = MainDataSource.CreateNavigator();

    string dataString = data.OuterXml;
    byte[] ba = Encoding.Default.GetBytes(dataString);

    MemoryStream dataStream = new MemoryStream(ba);
    return dataStream;
}

Tu sme sa len pripojili k hlavnému dátovému zdroju, vytvorili sme si MemoryStream a do tohto sme zapísali binárnu reprezentáciu vonkajšieho XML koreňového elementu dátového zdroja. Nakoniec potrebujeme vykonať transformáciu, v mojom prípade som jej výsledok (HTML) potreboval odoslať webovej službe a teda som ho potreboval dostať do BASE64 podoby:

private string GetHTMLBase64String()
{
    XmlDocument xml = new XmlDocument();
    xml.Load(GetDataStream());

    XmlReader xmlr = XmlReader.Create(GetViewStream());
    XslCompiledTransform xslt = new XslCompiledTransform();
    xslt.Load(xmlr);

    MemoryStream htmlStream = new MemoryStream();
    xslt.Transform(xml, null, htmlStream);

    htmlStream.Flush();
    htmlStream.Position = 0;

    byte[] ba = new byte[(int)htmlStream.Length];
    htmlStream.Read(ba, 0, ba.Length);

    return Convert.ToBase64String(ba);
}

V zásade transformácia prebieha takto:

  • Vytvoríme si XmlDocument a načítame do neho dáta
  • Vytvoríme si XmlReader a načítame do neho transformáciu
  • Vytvoríme si XslCompiledTransform a do nej transformáciu
  • Transformujeme do MemoryStreamu
  • Skonvertujeme Stream na BASE64 textový reťazec

A je to. Vytvoreniu InfoPath Formulára odosielajúceho súbor cez webovú službu som sa už venoval, takže to tu opakovať nebudem. Musím naozaj skonštatovať, že tvorba InfoPath formulárov je docela kreatívna a človek sa niekedy zapotí než nájde vhodné riešenie, ale je pekné vidieť, že InfoPath formuláre sú vďaka možnosti použitia .Net kódu veľmi silným nástrojom.

Mohlo by ťa tiež zaujímať

Páčil sa ti príspevok?

Zdieľaj príspevok alebo si ho odlož na neskôr

Sleduj ma

Ak nechceš premeškať príspevky ako je tento, sleduj ma na Twitteri, alebo ak máš RSS čítačku, môžeš sledovať môj RSS kanál.