XSLT (Extensible Stylesheet Language Transformations)
O XSLT
XSLT je XML formát, který je šablonou, která popisuje, jak se má obsah (jiného) XML zobrazit. Vychází se z myšlenky, že by se měl odělovat obsah od vzhledu. Jeden XML soubor obsahuje jen data (jako v příkladu níže adresar.xml obsahuje jen jména a adresy) a XSLT obsahuje šablonu, která říká, jak se má obsah XML zobrazit.
Jde vlastně o transformaci XML souboru do jiného XML souboru, nebo do HTML souboru, nebo třeba do obyčejného textového souboru. XSLT zkrátka říká, jak se má XML vykreslit.
Pokud vás XSLT nezaujme, nic si z toho nedělejte a klidně na něj zapomeňte. Tato technologie není v současnosti zrovna IN. Příklad použití s libxml2 je ale tak jednoduchý, že jsem prostě neodolal a musel ho napsat.
Příklad v XML
Podívejte se na příklad. Nejdříve XML soubor adresar.xml
.
Všiměte si, že v sobě obsahuje odkaz na XSLT soubor
<?xml-stylesheet type="text/xsl" href="adresar.xsl"?>
Tomuto odkazu rozumí například webové prohlížeče a tak vědí, odkud si stáhnout XSLT soubor.
DTD jsem tentokrát uložil do extra souboru adresar.dtd, viz
<!DOCTYPE adresare SYSTEM "adresar.dtd">
.
<?xml-stylesheet type="text/xsl" href="adresar.xsl"?>
<!DOCTYPE adresare SYSTEM "adresar.dtd">
<adresare>
<Adresar>
<firstName><![CDATA[Petr]]></firstName>
<lastName><![CDATA[Bílek]]></lastName>
<street><![CDATA[Národní]]></street>
<cisloPopisne><![CDATA[222]]></cisloPopisne>
<city><![CDATA[Kladno]]></city>
<psc><![CDATA[2545435]]></psc>
<phone><![CDATA[]]></phone>
</Adresar>
<Adresar>
<firstName><![CDATA[Jan]]></firstName>
<lastName><![CDATA[Svoboda]]></lastName>
<street><![CDATA[Bratří Trnků]]></street>
<cisloPopisne><![CDATA[4354353]]></cisloPopisne>
<city><![CDATA[Brno]]></city>
<psc><![CDATA[54543543]]></psc>
<phone><![CDATA[332 545 435]]></phone>
</Adresar>
<Adresar>
<firstName><![CDATA[Tomáš]]></firstName>
<lastName><![CDATA[Vomáčka]]></lastName>
<street><![CDATA[Kosmická]]></street>
<cisloPopisne><![CDATA[234]]></cisloPopisne>
<city><![CDATA[Praha 4]]></city>
<psc><![CDATA[345454]]></psc>
<phone><![CDATA[333222444]]></phone>
</Adresar>
<Adresar>
<firstName><![CDATA[Monika]]></firstName>
<lastName><![CDATA[Šustrová]]></lastName>
<street><![CDATA[Spálená]]></street>
<cisloPopisne><![CDATA[244]]></cisloPopisne>
<city><![CDATA[Praha 2]]></city>
<psc><![CDATA[546654]]></psc>
<phone><![CDATA[777444333]]></phone>
</Adresar>
<Adresar>
<firstName><![CDATA[Patrik]]></firstName>
<lastName><![CDATA[Kovář]]></lastName>
<street><![CDATA[Šílená]]></street>
<cisloPopisne><![CDATA[9]]></cisloPopisne>
<city><![CDATA[Postoloprty]]></city>
<psc><![CDATA[244544]]></psc>
<phone><![CDATA[608454544]]></phone>
</Adresar>
<Adresar>
<firstName><![CDATA[Rudolf]]></firstName>
<lastName><![CDATA[Mrázek]]></lastName>
<street><![CDATA[Zapadlá]]></street>
<cisloPopisne><![CDATA[0]]></cisloPopisne>
<city><![CDATA[Kostitřasy]]></city>
<psc><![CDATA[]]></psc>
<phone><![CDATA[555070070]]></phone>
</Adresar>
<Adresar>
<firstName><![CDATA[Kristýna]]></firstName>
<lastName><![CDATA[Vetchá]]></lastName>
<street><![CDATA[Pod Vodou]]></street>
<cisloPopisne><![CDATA[405]]></cisloPopisne>
<city><![CDATA[Praha 4]]></city>
<psc><![CDATA[454554]]></psc>
<phone><![CDATA[303565565]]></phone>
</Adresar>
<Adresar>
<firstName><![CDATA[Renike]]></firstName>
<lastName><![CDATA[Gáthy]]></lastName>
<street><![CDATA[Dunajská]]></street>
<cisloPopisne><![CDATA[333]]></cisloPopisne>
<city><![CDATA[Budapešť]]></city>
<psc><![CDATA[2454]]></psc>
<phone><![CDATA[5645455454]]></phone>
</Adresar>
<Adresar>
<firstName><![CDATA[Vladimír]]></firstName>
<lastName><![CDATA[Horlivý]]></lastName>
<street><![CDATA[Líná]]></street>
<cisloPopisne><![CDATA[3]]></cisloPopisne>
<city><![CDATA[České Budějovice]]></city>
<psc><![CDATA[446]]></psc>
<phone><![CDATA[4534535]]></phone>
</Adresar>
<Adresar>
<firstName><![CDATA[Petra]]></firstName>
<lastName><![CDATA[Kozáková]]></lastName>
<street><![CDATA[Zahradní]]></street>
<cisloPopisne><![CDATA[5454]]></cisloPopisne>
<city><![CDATA[New York]]></city>
<psc><![CDATA[4545]]></psc>
<phone><![CDATA[45335435]]></phone>
</Adresar>
</adresare>
Soubor adresar.dtd si můžete prohlédnout tady, ale pro tuto kapitolu je zcela bezvýznamný.
<!ELEMENT adresare (Adresar)*>
<!ELEMENT Adresar (firstName,lastName,street,cisloPopisne,city,psc,phone)>
<!ELEMENT firstName (#PCDATA)>
<!ELEMENT lastName (#PCDATA)>
<!ELEMENT street (#PCDATA)>
<!ELEMENT cisloPopisne (#PCDATA)>
<!ELEMENT city (#PCDATA)>
<!ELEMENT psc (#PCDATA)>
<!ELEMENT phone (#PCDATA)>
A tady je XSLT soubor adresar.xsl. Jak asi tušíte, převádí adrsar.xml do HTML. Jazyk XSLT v této kapitole popisovat nebudu (ani jiné), na to si najděte jiný tutoriál (pokud vás XSLT vůbec zajímá). Já vám jen ukáži, jak XSLT na XML aplikovat pomocí knihovny libxml2.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<head>
<title>Adresář</title>
<style type="text/css">
table {
border-collapse:collapse;
}
th,td {
padding:3px 5px;
text-align:left;
}
th {
border-bottom:3px solid black;
}
</style>
</head>
<body>
<h1>Adresář</h1>
<xsl:apply-templates></xsl:apply-templates>
</body>
</html>
</xsl:template>
<xsl:template match="adresare">
<table border="1">
<tr style="background:#00aaff;color:#ffffff;">
<th>Jméno</th><th>Příjmení</th>
<th>Ulice</th><th>ČP</th><th>Město</th><th>PSČ</th>
<th>Telefon*</th>
</tr>
<xsl:apply-templates select="Adresar">
<xsl:sort select="city"></xsl:sort>
<xsl:sort select="firstName" order="descending"></xsl:sort>
</xsl:apply-templates>
</table>
<em>*Povinná položka</em>
</xsl:template>
<xsl:template match="Adresar">
<xsl:if test="starts-with(city,'Praha')">
<tr bgcolor="#00fa00">
<xsl:for-each select="*">
<td><xsl:value-of select="."></xsl:value-of></td>
</xsl:for-each>
</tr>
</xsl:if>
<xsl:if test="not(starts-with(city,'Praha'))">
<tr>
<xsl:apply-templates></xsl:apply-templates>
</tr>
</xsl:if>
</xsl:template>
<xsl:template match="phone">
<xsl:choose>
<xsl:when test=". = ''">
<td bgcolor="red"><xsl:value-of select="."></xsl:value-of></td>
</xsl:when>
<xsl:otherwise>
<td><xsl:value-of select="."></xsl:value-of></td>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="*">
<td><xsl:value-of select="."></xsl:value-of></td>
</xsl:template>
</xsl:stylesheet>
Výsledek si můžete prohlédnout v každém dobrém webovém prohlížeči (Firefoxu) zde: adresar.xml. Nebo se podívejte na obrázek:
adresar.xml v prohlížeči Firefox.
Transforamce pomocí libxml2
Program funguje vcelku jednoduše. Nejdříve se nastaví nějaké globální parametry, pak se načtou XML a XSLT soubory, provede se transformace, transformace se uloží a uvolní se zdroje.
Volání funkce xmlSubstituteEntitiesDefault(1)
řekne libxml2, že má nahrazovat entity.
Jestli nevíte co jsou to entity, pak asi neznáte dokonale XML. Z toho si nic nedělejte :-).
Nastavení globální proměnné xmlLoadExtDtdDefaultValue na 1 zase libxml2 říká, že má
načítat externí XSLT soubory (pokud se na ně z XSLT odkazujete).
Volání xmlParseFile()
už znáte z povídání o DOM.
Funkce xsltParseStylesheetFile()
parsuje XSLT soubor.
Funkce xsltApplyStylesheet()
provede transformaci a
odkaz na výsledek vrátí v proměnné typu xmlDocPtr
. Jako třetí parametr
přebírá tato funkce nějké parametry, které jsou předávány do XSLT. Je to pole ukončené NULL,
obsahující dvojice název a hodnota parametrů (nebo taky nic, jako v příkladu).
Funkce xsltSaveResultToFile()
uloží výsledek do souboru.
V příkladu je prvním argumentem stdout
, tedy standardní výstup, takže
se transformace vypíše na obrazovku.
- /*------------------------------------------------*/
- /* 27dXslt/xslt.c */
- #include <string.h>
- #include <libxslt/xslt.h>
- #include <libxslt/transform.h>
- #include <libxslt/xsltutils.h>
- /* extern int xmlLoadExtDtdDefaultValue; */
- {
- xsltStylesheetPtr cur;
- xmlDocPtr doc, res;
- xmlSubstituteEntitiesDefault(1);
- xmlLoadExtDtdDefaultValue = 1;
- doc = xmlParseFile(xmlSoubor);
- res = xsltApplyStylesheet(cur, doc, params);
- xsltSaveResultToFile(stdout, res, cur);
- xsltFreeStylesheet(cur);
- xmlFreeDoc(res);
- xmlFreeDoc(doc);
- xsltCleanupGlobals();
- xmlCleanupParser();
- }
- /*------------------------------------------------*/
Na konci se volají funkce, které mají na starosti nezbytné uvolňování prostředků.
Nainstalujte si balíčky libxslt-devel
a
libxml2-devel
. Bez toho tento příklad nepřeložíte.
Překlad může vypadat takto:
Po spuštění programu se vám na obrazovku vypíše výsledné HTML.