uiListing
Egy olyan lista (listing) elem elkészítése volt a cél, amely az egyes oszlopok szerint rendezheto.
Feltétel volt, hogy a megírandó vezérlőelem minél rugalmasabb és univerzális legyen.
Követelmény volt:
- a fejlec (header) a html fileban legyen és nem az XSLT fileban. Például ha több nyelvű oldalunk van, akkor így egyszerűen
a HTML-t generáló szkript képes a fejlécet a választott nyelv függvényében kigenerálni és nem kell minden nyelvi verzióra egy külön XSLT filet készíteni, ami
csak a fejlécben különbözne.
- olyan univerzális legyen, hogy tetszőleges számú oszlop esetén is működjön. A rekordok az XML fileban vannak és az XSLT stílus annyi
oszlopot generál, ammennyit kell. Természetesen a HTML fileban is pont ennel megfelelő számú oszlopopból álló fejlécet kell elhelyezni.
Igy eltérő számú oszlopokat tartalmazó XML fileok ugyanazt az XSLT stílust használhatják, nem kell emiatt új XSLT filet keszíteni.
- A rendezés kliens oldalon történjen. Bármely oszlop szerint lehessen rendezni. Az oszlopok rendezésekor ugyanazt az XSLT filet kell használni.
Nem lehet, hogy ha a 2. oszlopot akarom rendezni, akkor meghívok egy másik XSLT stílust.
- A HTML-be ágyazandó kód lehetőleg rövid legyen. Egy HTML oldalba tetszőleges számú vezérlőelemt lehessen tenni (név konfliktus és egyéb kolíziókat kizárni)
Megoldás:
A követelmények teljesitése egyáltalán nem volt könnyű.
Mindjárt az első fejtörést a fejléc okozta. Ugyanis a fejléc oszlopainak pontosan ugyanolyan szélesnek kell lennie,
mint az adatok oszlopainak. Ugyanis előre nem lehet tudni, hogy milyen szélesek lesznek az egyes oszlopok.
Igy az egyetlen megoldás, ha a lista egy <table> elemben lesz. A problémát az okozza, hogy
az XSLT transzformációból keletkező táblából és a fejléc táblából egyetlen táblázatot kell készíteni.
Az első legegyszerűbb megoldás kivitelezhetetlennek bizonyult. A fejléc (és később az egész lista elem) egy DIV tagban lenne.
<DIV id="uiListing_01" class=clsContent>
<table>
<tbody class="uiCaptionBar">
<td>nev</td>
<td>utca</td>
<td>telefon</td>
</tbody>
</DIV>
Úgy okoskodtam, hogy a DIV tagban lévő fejlécet nem zárom le a </table> lezáró elemmel. A transzformáció után kapott
táblázatot (table tag nélkül) bemásolom a fejléc mögé, majd lezárom a hiányzó </table> taggal.
var oContainer = document.getElementById("uiListing_01");
oContainer.innerHTML = oContainer.innerHTML + sXMLResult +'</table>';
A problémát a lezáratlan táblázat okozta. A oContainer.innerHTML nem csak a DIV tag közti HTML kódot adta vissza, hanem annál jóval többet.
A transzformáció után kapott result (XML kód) tetején egy PI (feldolgozásvezérlő instrukció) tag volt: <?xml version="1.0"?>
És így ezzel a PI taggal a tetején nem lehet beszúrni a table tagba, hisz nem oda való.
Erre megírtam egy egyszerű segédmetódust ClearXML. Ez a metódus sztring műveletekkel eltávolítja az első PI tagot. (elég az elsőt, mert több úgy sincsen).
Azért azt hiszem ez a PI tag azért van az XML tetején, mert az XSL stílusfájl tetejéből származik. Szóval azt hiszem, hogy elég lett volna
az XSL fájl tetejéből leszedni ezt a PI tagot. De most már mindegy.
Mivel az előbbiekben kiderült, hogy muszály lezárni a táblázatot, ígyhát lezártam azt.
A végső megoldás tehát egy kis DOM manipuláció. Az XSL fájlban lévő táblázat lesz a mi végső táblázatunk.
Először elmentem a DIV tartalmát. Majd a transzformáció eredményével (a PI tagtól megtisztítva) felülírom a DIV tartalmát.
(az előbb elmentettem a benne lévő fejlécet).
Most már ottvan a táblázatunk a helyén, de még hiányzik a fejléc. A fejléc egyelőre egy változóba lett elmentve.
Szóval az elmentett fejlécből kiszedem a TBODY tagot és beszúrom a már DIV tagban lévő táblázat TABLE tag első gyermek elemeként.
Ezzel meg is oldottam az első problémát. A második ugyancsak nagy fejtörést okozó problémát a rendezés okozta.
Mivel még nem ismertem eléggé az XSLT nyelvet, úgy gondoltam, hogy a rendezés megoldható egy paraméter átadásával a köv.
képpen.
<xsl:param name="sortBy"></xsl:param>
<xsl:sort select="$sortBy"/>
Mint később megtudtam, XSLT-ben nincs mód arra, hogy egy paraméter tartalmával rendezzünk.
Az Interneten találtam egy trükköt, de nem az igazi:
<xsl:sort select="*[name()=$param]"/>
A $param paraméter mindig csak egy elem nevét tartalmazhatja, tehát nem lehet egy elem attribútuma szerint rendezni.
További keresgélés után lehúztam jópár XSLT példa fájlt. A rendezésre a másik használatos módszer az, hogy több
stílust használnak. Mindig a rendezni kívánt oszlopnak megfelelő XSLT stíluslapot használnak. Vagyis ha a táblázatunk 10
oszloppól áll, akkor kénytelenek vagyunk létrehozni 10 stíluslapot.
Számomra ez a megoldás elfogadhatatlan volt. Csak arra lett volna szükség, hogy valaki vagy valami a megfelelő rendezési
kifejezést betegye az xsl:sort elem select attribútumába. Eszembe jutott, hogy az XSLT lapot szerver oldali parancsnyelv is
generálhatná. getstyle.asp?orderBy=Company
Ez a megoldás sem tetszett. Ilyenkor ugyanis amikor a felhasználó rákattint a fejléc egyik oszlopára, akkor várni kell, amig a
szervertől megkapjuk a módosított stíluslapot.
Ekkor jutott az eszembe, hogy miért nem módosítom a stíluslapot kliens oldalon. Elvégre egy XSLT stíluslap nem más, mint
egy XML fájl.
Az XSL stílusnak létrehoztam a DOM fáját (xmlDoc). A getElementsByTagName metódus segítségével kikerestem a módosítani
kívánt XSLT elemet. Az elem bármelyik attribútumát a setAttribute nevű metódussal lehet módosítani.
A módositott DOM -fát visszaírtam egy XML szigetbe.
var oElement = xmlDoc.getElementsByTagName("xsl:sort");
oElement.item(0).setAttribute('select', sortBy);
oElement.item(0).setAttribute('order', order);
oElement.item(0).setAttribute('data-type', dataType);
Szabó Attila (2003, július 3.)