Lucrarea 3
Download: PDF ODT
Rezumat
- Principii
- În contextul unui nod, se pot face prelucrări (formatare, afişare, etc.) cu elementul în sine, descendenţii şi precedenţii săi.
- În contextul unei liste de noduri, aceasta poate fi reordonată; poate fi accesat fiecare element al listei, prin poziţia sa.
- Ieşirea poate fi controlată strict atât prin şabloane potrivite, cât şi prin instrucţiuni de control: if, choose.
- Şabloanele se aplică începând cu rădăcina arborelui XML.
- Există un mod implicit de prelucrare a arborelui, în lipsa unui şablon potrivit: se transformă toate nodurile descendente direct.
- Odată găsit un şablon, prelucrarea contextului curent încetează (în lipsa unei instrucţiuni apply-templates).
- Instrucţiunile de procesare (<? ... ?>) sunt trimise la ieşire folosind <xsl:processing-instruction> (de ex. pentru <?xml-stylesheet.. ?>) sau folosind <xsl:output> (pentru <?xml.. ?>).
- Cuvinte cheie
- xsl:sort, xsl:if, xsl:choose, xsl:apply-templates, xsl:processing-instruction
- Predicatul contains()
Elementul <xsl:sort>
O opţiune pentru afişarea listei cu CD-uri ar putea fi de exemplu afişarea acestora în ordine alfabetică după autor. Realizarea acestui lucru se poate face deosebit de simplu prin adăugarea unui singur element: <xsl:sort>.
- Modificare în catalog.xsl
<xsl:for-each select="catalog/cd">
<xsl:sort select="artist"/>
<tr>
<td>
<xsl:value-of select="title"/>
</td>
<td>
<xsl:value-of select="artist"/>
</td>
</tr>
</xsl:for-each>
Porţiunea de document de mai sus afişează lista CD-urilor sortate în ordine alfabetică după artist.
Sintaxa xsl:sort
<xsl:sort select="expresie" lang="limbaj" data-type="text|number|qname" order="ascending|descending" case-order="upper-first|lower-first"/>
Atribute:
- select (opţional) – O expresie XPath care specifică nodurile care vor fi sortate.
- lang (opţional) – Specifică limbajul care va fi folosit în procesul de sortare.
- data-type (opţional) – Specifică tipul de datelor ce vor fi sortate. În mod implicit are valoarea “text”.
- order (opţional) – Specifică ordinea sortării. În mod implicit are valoarea “ascending”.
- case-order (opţional) – Specifică dacă primele care vor fi sortate vor fi literele mici sau literele mari.
Deci dacă am dori un tabel care să includă cd-urile în ordine descrescătoare a preţului lor atunci ar trebui să adăugăm în documentul XSL o linie de genul:
- Modificare în catalog.xsl
<xsl:sort select="price" order="descending" data-type="number"/>
Într-un ciclu <xsl:for-each/> sau <xsl:apply-templates/> se pot adăuga mai multe elemente <xsl:sort/> :
<xsl:for-each select="catalog/cd">
<xsl:sort select="artist"/>
<xsl:sort select="price" order="descending" data-type="number"/>
<tr>
<td>
<xsl:value-of select="title"/>
</td>
<td>
<xsl:value-of select="artist"/>
</td>
</tr>
</xsl:for-each>
Dacă nu am fi specificat tipul datelor ce vor fi sortate, ele ar fi fost considerate de
tip text iar rezultatul ar fi fost altul. Numerele ar fi fost comparate caracter cu
caracter şi am fi avut rezultate de genul 9 > 10 deoarece 9 > 1.
Elementul <xsl:if>
Dacă în cadrul documentului XSL sunt necesare anumite decizii care trebuie luate în funcţie de conţinutul documentului sursă atunci cea mai simplă soluţie este apelarea la elementul <xsl:if>. Acesta funcţionează prin trimiterea la ieşire a conţinutului său doar dacă o anumită condiţie este îndeplinită. De exemplu, să presupunem că dorim să subliniem vizual diferenţa dintre preţurile CD-urilor, colorându-le diferit pe cele mai scumpe de 10€. Porţiunea din documentul XSL ce ar trebui schimbată este următoarea:
- Modificare în catalog.xsl
<xsl:for-each select="catalog/cd">
<xsl:if test="price>10">
<tr>
<td bgcolor="#ccff00">
<xsl:value-of select="title"/>
</td>
<td bgcolor="#ccff00">
<xsl:value-of select="artist"/>
</td>
</tr>
</xsl:if>
<xsl:if test="price<=10">
<tr>
<td bgcolor="#66ffff">
<xsl:value-of select="title"/>
</td>
<td bgcolor="#66ffff">
<xsl:value-of select="artist"/>
</td>
</tr>
</xsl:if>
</xsl:for-each>
Se observă că acest lucru l-am realizat cu ajutorul a două elemente <xsl:if> şi nu cu unul singur, pentru că elementul <xsl:if> nu pune la dispoziţie şi o ramură “else”, aşa cum se întâmplă la alte limbaje de programare.
Sintaxa xsl:if
<xsl:if test="expresie">
<!-- Continut -->
</xsl:if>
Atribut:
- test (necesar) – Specifică condiţia ce va fi testată.
Evaluarea condiţiei din atributul test se face după câteva reguli stricte:
- dacă expresia din condiţie specifică o mulţime, atunci condiţia este adevărată dacă mulţimea conţine cel puţin un element.
- dacă expresia din condiţie specifică un şir de caractere, atunci condiţia este adevărată dacă acesta nu este vid.
- dacă expresia din condiţie specifică un număr, atunci condiţia este adevărată dacă acesta nu are valoarea 0.
Elementul <xsl:choose>
În cazul în care este necesară prelucrarea documentului sursă în funcţie de mai multe condiţii, utilizarea elementului <xsl:if> devine greoaie deoarece trebuie folosit pentru fiecare caz în parte. Se poate folosi totuşi elementul <xsl:choose>. El pune la dispoziţia programatorului un mecanism similar celui oferit de switch / case din C.
Sintaxa xsl:choose
<xsl:choose>
<!-- Continut -->
</xsl:choose>
Sintaxa impune prezenţa în interiorul elementului <xsl:choose> a cel puţin unui element <xsl:when> şi a cel mult unui element <xsl:otherwise>. Exemplul tratat în cazul elementului <xsl:if> ar putea fi rezolvat utilizând elementul <xsl:choose> astfel:
- Modificare în catalog.xsl
<xsl:for-each select="catalog/cd">
<xsl:choose>
<xsl:when test="price>10">
<tr>
<td bgcolor="#ccff00">
<xsl:value-of select="title"/>
</td>
<td bgcolor="#ccff00">
<xsl:value-of select="artist"/>
</td>
</tr>
</xsl:when>
<xsl:otherwise>
<tr>
<td bgcolor="#66ffff">
<xsl:value-of select="title"/>
</td>
<td bgcolor="#66ffff">
<xsl:value-of select="artist"/>
</td>
</tr>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
Sintaxa elementului <xsl:when> seamănă cu cea a elementului <xsl:if>; elementul <xsl:otherwise> nu are nici un atribut. Regulile care guvernează evaluarea elementului <xsl:choose> sunt simple: prima condiţie adevărată din cadrul elementelor <xsl:when> duce la trimiterea la ieşire a elementului when respectiv. Dacă nici o condiţie din cadrul elementelor <xsl:when> nu este adevărată, atunci se evaluează elementul <xsl:otherwise> (dacă acesta lipseşte, atunci nimic nu este trimis la ieşire). Evaluarea condiţiilor din cadrul elementelor <xsl:when> este identică cu cea din cadrul elementelor <xsl:if>.
Elementul <xsl:apply-templates>
Până acum întreaga procesare a documentului sursă a fost făcută folosind un singur şablon. Acest lucru împiedică folosirea unei abordări modulare a prelucrării, sarcina creării documentului revenind în întregime unui singur programator. Folosind însă elementul <xsl:apply-templates> se poate modulariza documentul XSL, facilitând totodată şi împărţirea sarcinilor între mai multe echipe de exemplu. Să considerăm pentru început următorul document XSL:
- Noul format pentru catalog.xsl
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h2>My CD Collection</h2>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="cd">
<p>
<xsl:apply-templates select="title"/>
<xsl:apply-templates select="artist"/>
</p>
</xsl:template>
<xsl:template match="title">
Title: <span style="color:#ff0000">
<xsl:value-of select="."/>
</span>
<br />
</xsl:template>
<xsl:template match="artist">
Artist: <span style="color:#00ff00">
<xsl:value-of select="."/>
</span>
<br />
</xsl:template>
</xsl:stylesheet>
Acum şablonul pentru nodul rădăcină nu mai conţine toată informaţia de procesare ci doar creează un document HTML gol al cărui conţinut este generat de alte şabloane. Prin existenţa elementului <xsl:apply-templates> în interiorul acestuia se specifică faptul că în acest loc vor fi inserate ieşirile generate de celelalte şabloane. Trebuie avut în vedere contextul fiecărui nod din documentul sursă, deoarece unele noduri pot să apară în mai multe contexte, tratarea uniformă putând genera inadvertenţe. Şabloanele vor fi aplicate nodului curent precum şi descendenţilor acestuia în funcţie de atributele elementului <xsl:apply-templates>.
Sintaxa apply-templates
<xsl:apply-templates select="expresie" mode="mod">
<!-- Continut:(xsl:sort|xsl:with-param)* -->
</xsl:apply-templates>
Atribute:
- select (opţional) – Expresie XPath care specifică nodurile ce vor fi procesate. Dacă acest atribut este omis atunci sunt procesate toate nodurile descendente ale nodului curent.
- mode (opţional) – Dacă se doresc mai multe moduri de procesare a unui document atunci cu ajutorul acestui atribut se poate selecta între ele.
Elementul <xsl:processing-instruction>
Dacă dorim să generăm un alt document XML pornind de la un document dat vom observa că nu vom putea trimite la ieşire linia <?xml-stylesheet type="text/xsl" href="catalog2.xsl"?> deoarece aceasta este o instrucţie de procesare şi în mod normal aceasta nu va fi trimisă la ieşire, ci interpretată.
Sintaxa processing-instruction
<xsl:processing-instruction name="instructiune procesare">
<!-- Continut -->
</xsl:processing-instruction>
Atribut:
- name (necesar) – Denumirea instrucţiei de procesare ce va fi trimisă la ieşire. De exemplu instrucţia de procesare de mai sus va fi trimisă prin intermediul următorului cod:
- Conţinut catalog3.xsl
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method = "xml" encoding="ISO-8859-1" version="1.0" />
<xsl:template match="/">
<xsl:processing-instruction name="xml-stylesheet">type="text/xsl" href="catalog2.xsl"</xsl:processing-instruction>
<colectie></colectie>
</xsl:template>
</xsl:stylesheet>
TEMĂ
1. Se consideră următorul fişier (“agenda.dtd”) care are rolul de a valida un document XML ce conţine intrările dintr-o agendă:
Definiţia tipului documentului XML, fişier agenda.dtd
<!ELEMENT agenda (persoana)+ >
<!ELEMENT persoana (nume, prenume, varsta, adresa, email, tel, poza?) >
<!ATTLIST persoana id CDATA #REQUIRED >
<!ELEMENT nume (#PCDATA) >
<!ELEMENT prenume (#PCDATA) >
<!ELEMENT varsta (#PCDATA) >
<!ELEMENT adresa (#PCDATA) >
<!ELEMENT email (#PCDATA) >
<!ELEMENT tel (#PCDATA) >
<!ELEMENT poza (#PCDATA) >
2. Scrieţi un document XML simplu care să respecte restricţiile de mai sus.
3. Să se scrie un document XSL cu ajutorul căruia se extrag şi se afişează din documentul creat un tabel ce va conţine doar numele, prenumele şi telefonul persoanelor. Agenda va fi însă afişată în ordinea descrescătoare a vârstei persoanelor.
4. Persoanele care sunt dintr-o anumită localitate să fie afişate într-o culoare distinctă. Obs. Se va folosi funcţia XPath contains().
5. Să se scrie un document XSL care va crea un nou document XML din documentul de mai sus, care va conţine doar numele şi telefonul persoanelor cu vârsta sub 20 de ani.
Sintaxa contains
contains(şir, subşir)
Atribute:
- şir – şirul în care se caută apariţia subşirului.
- subşir – subşirul căutat.