[ Webhosting profitux.cz ]
hertpl: Undefined index: page_title(template line: 74) in templates/articles_print.html on line 39

XSLT a JavaScript

Klíčová slova: JavaScript, XML a XSLT transformace

Úvod

Dokumenty XML (můžeme rovnou říct, že narozdíl od dokumentů (X)HTML) nenesou žádnou informaci, která by prohlížeči sdělila, jakým způsobem se má ten či onen element zobrazit, jakou má mít text v daném elementu barvu, jaké má být použito písmo, či třeba jaká má být barva pozadí. Proto je do většiny moderních prohlížečů integrován takzvaný XSLT Processor. Ten zpracovává daný XML dokument spolu s tzv. XML Stylesheetem (XSL) a transformuje tak daný XML dokument např. do XHTML (nebo i do libovolného jiného XML dokumentu), čímž pomáhá prohlížeči konkretizovat vzhled jednotlivých částí XML dokumentu. Popis jazyka pro XSLT (XSLT je natolik silné, že je možno hovořit dokonce o programovacím jazyku) je mimo rámec tohoto textu. U čtenáře se v tomto směru předpokládá jistá základní erudice. Zmíníme jen, že XSLT je rovněž založeno na XML. Článek si klade za úkol vysvětlit mírně pokročilým tvůrcům webových aplikací, jak XSLT používat v prohlížečích právě pomocí JavaScriptu.

V následujícím textu si ukážeme kusy zdrojových kódů, na kterých je možno XSLT transformaci otestovat. Potřebujeme tedy:

  • XML soubor, který bude transformován
  • XML Stylesheet kterým budeme transformovat
  • JavaScript funkce

XSLT pomocí JavaScriptu v Mozille (... Opeře a Safari)

Prohlížeče z rodiny Mozilla používají (od verze 1.2) pro XML Transformace engine TransforMiiX.

Pro používání XSLT v Mozille je nejprve nutné vytvořit objekt XSLTProcessor. Následně je nutno importovat do tohoto objektu stylesheet voláním funkce importStyleshe­et(Node). Parametr Node určuje uzel XML dokumentu, který obsahuje popis XML transformací. Ten je samozřejmě možno získat více způsoby - můžeme například XSLT dokument "sestavit na místě", načíst jej pomocí metody document.load("xmldoc­.xml") nebo je i možné využít AJAX a dotázat se na responseXML (např. chceme-li dělat XML Transformace "za běhu", to znamená nejen po načtení stránky). My si zde ukážeme poslední jmenovaný postup, protože je pravděpodobně nejvíce obecný a je zároveň nejčastěji uváděn v jiných tutoriálech.

Pro provedení transformace samotné máme k dispozici dvě metody objektu typu XSLTProcessor.

Metoda XSLTProcessor::tran­sformToDocumen­t(xmlfile_xml) přijímá jeden argument a tím je XML dokument, který chceme transformovat pomocí importovaného XML stylesheetu a jako výsledek vrací celý DOM dokument.

Metoda XSLTProcessor::tran­sformToFragmen­t(xmlfile_xml, ownerObj) vrací "pouze" DOM DocumentFragment Node, který se může následně připojit k jinému dokument objektu. Proto tato metoda přijímá ještě druhý parametr, který tento objekt specifikuje (každý fragment musí patřit dokumentu). Metoda transformToFrag­ment je tedy o něco obecnější a je proto v mnoha případech vhodnější. Samozřejmě si musíme také načíst XML dokument, který chceme transformovat. Celý níže uvedený kód zavoláme například při načtení elementu body, tedy <body onload="Transfor­m()">.

Nezapomínejme, že tento kód nefunguje v prohlížeči Internet Explorer!

function Transform(xsltFile, xmlFile, whereToWrite) { // not for IE!!!
  // Vytvorime objekt XSLTProcessor
  var xsltProc = new XSLTProcessor();
 
  // Vytvorime objekt pro HTTP zadosti
  var xmlhttp = new XMLHttpRequest();
 
  // Ziskame XML dokument s popisem transformaci
  xmlhttp.open("GET", xsltFile, false);
  xmlhttp.send(null);
  var xslStylesheet = xmlhttp.responseXML;
 
  // Importujeme stylesheet
  xsltProc.importStylesheet(xslStylesheet);
 
  // Nacteme XML soubor ktery chceme transformovat
  xmlhttp.open("GET", xmlFile, false);
  xmlhttp.send(null);
  var xmlDoc = xmlhttp.responseXML;
 
  // Provedene transformaci XML dokumentu
  // Tento kod je ekvivalentni volani transformToDocument
  var fragment = xsltProc.transformToFragment(xmlDoc, document);
 
  // Zapiseme do elementu s id=whereToWrite
  document.getElementById(whereToWrite).appendChild(fragment);
}

Více informací lze najít na stránkách Mozilly na stránce: Using the Mozilla JavaScript interface to XSL Transformations

XSLT v MS Internet Exploreru 7

Přístup k XML Transformacím je v MS Internet Exploreru oproti Mozille poněkud odlišný - XSLT je součástí MSXML (Microsoft XML Core Services). Nejjednodušší způsob (uvedený na MSDN), jak používat XSLT v prohlížeči IE je upravit funkci Transform do níže uvedené podoby (ostatní soubory můžeme nechat tak jak jsou). Využíváme zde ActiveX objekty pro vytvoření XML HTTP requestů. Důležitá je zde především metoda transformNode(xslt), která transformuje XML uložené v srcTree pomocí stylesheetu načteného v xsltTree.

Toto řešení funguje pouze v Internet Exploreru (testováno bylo ve verzi 7).

function Transform(xsltFile, xmlFile, whereToWrite) { // just for IE!!!
  // vytvorime XMLHTTP Request pro XML
  var srcTreeXMLhttp = new ActiveXObject("Msxml2.XMLHTTP");
  srcTreeXMLhttp.open("GET", xmlFile, false);
  srcTreeXMLhttp.send(null);
 
  // Ulozime zdrojove XML
  srcTree = srcTreeXMLhttp.responseXML;
 
  // Vytvorime XMLHTTP Request pro XSLT
  var xsltTreeXMLhttp = new ActiveXObject("Msxml2.XMLHTTP");
  xsltTreeXMLhttp.open("GET", xsltFile, false);
  xsltTreeXMLhttp.send(null);
 
  // Ulozime transformace (XSLT)
  xsltTree = xsltTreeXMLhttp.responseXML;
 
  // Zapiseme transformovany XML kod
  document.getElementById(whereToWrite).innerHTML = srcTree.transformNode(xsltTree);
}

Více informací lze najít na stránkách Microsoftu na stránce: XSLT for MSXML

Implementace fungující jak v IE tak v Mozille a Opeře

Asi je přirozené, že řešení které funguje pouze v jednom ze dvou majoritních prohlížečů není příliš zajímavé. Proto se pokusím napsat řešení, které funguje v obou prohlížečích. De facto si rozdělíme celý kód na dva případy dle prohlížečů. Takto provedeme transofrmaci nezávisle na prohlížeči. Ve skriptu nejprve získáme XML dokument, který budeme chtít transformovat, poté soubor s XSLT a nakonec provedeme transformaci samotnou.

function Transform(xsltFile, xmlFile, whereToWrite) {
  var xmlHttp;
  var xsltHttp;
  if (window.XMLHttpRequest) {
    // Mozilla + Opera + Safari
    xmlHttp = new XMLHttpRequest();
    xsltHttp = new XMLHttpRequest();
  } else if (window.ActiveXObject) {
    try {
      // MSIE 6+
      xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
      xsltHttp = new ActiveXObject("Msxml2.XMLHTTP");
    } catch (e) {
      try {
        // MSIE 5.5+
        xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
        xsltHttp = new ActiveXObject("Microsoft.XMLHTTP");
      } catch (e) {
        return false;
      }
    }
  } else return false;
  xmlHttp.open("GET", xmlFile, false);
  xmlHttp.send(null);
  var XML = xmlHttp.responseXML;
  xsltHttp.open("GET", xsltFile, false);
  xsltHttp.send(null);
  var XSLT = xsltHttp.responseXML;
  var xsltProc;
  if (typeof XSLTProcessor != "undefined") {
      xsltProc = new XSLTProcessor();
      xsltProc.importStylesheet(XSLT);
      var fragment = xsltProc.transformToFragment(XML, document);
      document.getElementById(whereToWrite).appendChild(fragment);
  } else {
      document.getElementById(whereToWrite).innerHTML = XML.transformNode(XSLT);
  }
}

Tento kód byl otestován a funkční v MS IE 7, Mozilla Firefox 2, Opera 9, Safari 3 for Windows. Nefunguje v prohlížeči Konqueror (Linux).

Využití: Zobrazování cizích RSS kanálů na svých stránkách

Výše uvedený kód je možno upravit tak, aby posloužil ke zobrazování cizích RSS kanálů na stránkách. Je však nutno přenést část úkolů spojených se získáváním RSS kanálu na server-side skriptování, například v PHP. Není totiž možné (z bezpečnostních důvodů) volat metodu XMLHTTPReques­t::open (ale ani třeba document::load) do jiné než vlastní domény. Zde si ukážeme pouze nejjednodušší možný skript (rss.php), průměrně zdatný PHP kodér si skript odpovídajícím způsobem upraví.

// Soubor: rss.php
// Posilani obsahu RSS kanalu jako XML
  header("Content-type: Text/xml");
  echo file_get_contents("http://www.zive.cz/default.aspx?server=1&section=47&rss=1");

Tento skript dělá následující: na serveru se pomocí funkce file_get_contents stáhne obsah RSS kanálu a ten se pomocí funkce header odešle jako Mime-type Text/XML (je samozrejmě možné specifikovat i kódování znaků). Máme tedy skript uložený na našem serveru, který posílá RSS obsah, získaný pomocí server-side skriptování z jiné domény. Nyní je tedy možno použít upravenou metodu UniversalTran­sform() (XMLHTTPReques­t::open už projde, skript rss.php, který posílá obsah RSS kanálu ve formě XML, je u nás na doméně) - stačí jako soubor xmlFile zadat "rss.php". Samozřejmě je nutné použít vhodný XSLT stylesheet, jendoduchý si můžete zkopírovat například tady:

<?xml version="1.0" encoding="iso-8859-2" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" omit-xml-declaration="no" indent="yes" encoding="utf-8" media-type="text/xml; charset=utf-8" />
  <xsl:template match="rss/channel">
    <html>
      <head>
        <title>
          <xsl:value-of select="title"/> - <xsl:value-of select="lastBuildDate"/>
          </title>
      </head>
      <body>
        <div id="obsah">
          <h1 class="rss_channel">
            <a>
              <xsl:attribute name="href">
                <xsl:value-of select="link"/>
              </xsl:attribute>
              <xsl:attribute name="onclick">
                <xsl:text>
                  return !window.open(this.href);
                </xsl:text>
              </xsl:attribute>
              <xsl:value-of select="title"/>
            </a>
          </h1>
          <p>
           <xsl:value-of select="description" disable-output-escaping="yes" />
          </p>
          <hr />
          <xsl:for-each select="//item">
            <span class="rss_topic">
              <xsl:attribute name="title">
                <xsl:value-of select="pubDate"/>
              </xsl:attribute>
              <a>
                <xsl:attribute name="href">
                  <xsl:value-of select="link"/>
                </xsl:attribute>
                <xsl:attribute name="onclick">
                  <xsl:text>
                     return !window.open(this.href);
                  </xsl:text>
                </xsl:attribute>
                <xsl:value-of select="title"/>
              </a>
            </span>
            <p class="rss_description">
              <xsl:value-of select="description" disable-output-escaping="yes" />
            </p>
          </xsl:for-each>
        </div>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

Komentáře čtenářů

skebla@zoznam.sk (2009-01-10 08:04:47)

Učil som sa sám html a aj javacript, ale doteraz neviem jedno ako možem docieliť to ,že sa mi budu javascripty zobrazovať rovnako v explorery tak aj v iných prehliadačoch.Mám skúsenosti z tým,že čo mi ide v explorery mi nejde v mozzile a co mi ide v mozzile nejde mi v explorery malo kedy mi to funguje na viacerých prehliadačoch. Poprosil by som o vysvetlenie ako to možem dosiahnuť.Ďakujem

Petr Dvorak (2009-01-10 19:05:43)

Ahoj,

jednou z tech moznosti jak docilit toho, ze javascript funguje ve vetsine prohlizecu je to, co jsem jiz naznacil v tomto clanku. To znamena rozdelovat kod podle typu prohlizece. Vim, ze to muze znit kostrbate, ale bohuzel to casto je nevyhnutelne (to znamena opravdu to NEJDE v teto dobe resit jinak, nez delenim kodu dle prohlizece). Ruzne prohlizece pouzivaji ruzne interpretery JavaScriptu a jine konstrukce pro stejnou vec.

Kazdopadne existuje "jaksi standardizovany JavaScript" (ECMA script), takze to je dobre misto kde zacit (je dobre zacit u standardu a odchylky pak resit operativne). JavaScript Language Reference (ECMA) popisujici ECMAScript je k dispozici online (viz link)...

Prakticky orientovanejsi jsou treba stranky w3schools.com, kde je cely learning trail pro JavaScript (ktery pro zacatek rozhodne bude stacit)...

Pokud se dotaz tykal i spatneho zobrazovani HTML/CSS, tak tam je situace podle me o neco jednodussi. Staci znat alespon ramcove standardy pro (X)HTML/CSS, ktere jsou na webu w3.org (napr. zde lze zacit pro HTML) a je z poloviny vyhrano. Dodrzovani standardu se da navic zkontrolovat online pomoci validatoru HTML ci validatoru CSS. Validatoru staci zadat url nebo kod a on Ti rekne, zda je stranka/styl validni (v souladu se standardem) ci neni...

Napriklad toto jsou vysledky validace pro tuto stranku:

  • CSS (obsahuje warningy, ktere jsem ale liny opravit, ne errory)
  • HTML

Dale - dnes existuji 4 nejdulezitejsi prohlizece (a jejich verze/modifikace): MSIE, Mozilla Firefox, Opera a Safari. Podle me by melo pro bezny web stacit testovat v IE6 a ve Firefoxu 3... IE7 je pomerne dobre kompatibilni, cili bude stranky zobrazovat podobne jako treba Firefox, Opera/Safari se taktez moc lisit nebudou, testovani na nich bych provadel formou sanity testu ("proklikat to cas od casu...").

Doufam, ze jsem pomohl,

Petr Dvorak

(2010-10-22 08:55:38)

Ahoj, moc se nevyznám a chci se zeptat jak se funkce Transform(xsltFile, xmlFile, whereToWrite) zavolá.

Mám to takto
 

Děkuji moc