XML pro web aneb od teorie k praxi, 12.díl

V dnešním dílu se budeme zabývat elegantním načtením XML dokumentu čistě pomocí skriptování. Připraven je i bonus, který vám pomůže obejít jednu málo známou chybu projevující se při práci s DOM XML dokumentem v IE.

Načtení XML dokumentu v Mozille - DOM

V normě DOM Level 2 Core byla přidána možnost vytvoření nového DOM XML dokumentu pomocí metody createDocument() objektu implementation. V současné době lze tímto způsobem vytvářet DOM XML dokument pouze v Mozille, která má ze všech prohlížečů zdaleka nejlepší implementaci DOM. Vytvoření nového DOM XML dokumentu je záležitostí jednho řádku skriptu.

var xmlDoc = document.implementation.createDocument(``, ``, null);

Metoda createDocument() má tři parametry - popořadě jsou to string namespaceURI (identifikátor jmenného prostoru, kterým je URI), string qalifiedName (kvalifikované jméno kořenového elementu dokumentu, tj. jméno, které může obsahovat předponu jmenného prostoru) a objekt doctype. Proměnná xmlDoc nyní obsahuje DOM reprezentaci XML dokumentu, který jsme však vytvořili úplně prázdný - neobsahuje ani kořenový element, ani deklaraci typu dokumentu. Tento minimalistický DOM dokument se však nejlépe hodí k načtení XML z externího zdroje. Nyní si ukážeme další dva kroky, které nás dovedou až k cíli, kterým je načtený XML dokument.

xmlDoc.onload = zpracujXMLdokument;
xmlDoc.load(`cesta/k/xml/dokumentu.xml`);

Nejprve zaregistrujeme ovladač události load, která nastane v okamžiku dokončení načtení XML dokumentu. V našem případě se jedná o funkci s názorným názvem zpracujXMLdokument() - může se jednat např. o výpis dat z XML do HTML stránky, jehož příklad jsme si uváděli minule, ale také se samozřejmě může jednat o jakoukoliv jinou funkci, kterou potřebujeme spustit bezprostředně po načtení XML souboru.

Druhým krokem je samotné načtení dokumentu, které zajišťuje metoda load() aplikovaná na samotný DOM XML dokument. Metoda load() byla zařazena do normy DOM Level 3 Load and Save. Jediným parametrem metody je relativní či absolutní URL XML dokumentu, který potřebujeme načíst. Je však potřeba si dát pozor na to, aby XML dokument pocházel ze stejné domény, jako "mateřská" HTML stránka, v opačném případě prohlížeč z důvodu bezpečnostních restrikcí načtení XML dokumentu neprovede.

Vytváření DOM XML dokumentu v prohlížeči

DOM XML dokument vytvořený metodou createDocument() nemusí být určen jen pro načtení externího XML dokumentu. Je možné jej použít jako základ pro vytvoření samostatného DOM XML dokumentu - všechny možnosti pro vytváření, přidávání, procházení či mazání nodů, které nám poskytuje DOM rozhraní, lze aplikovat i na tento "neviditelný" dokument. V přemýšlivých hlavách z řad čtenářů se nyní jistě objeví logická otázka - a k čemu se takový "neviditelný" XML dokument hodí? Byla by to opravdu spíše jen hračka bez užitku, kdyby neexistovaly techniky, kterak tento XML dokument "zhmotnit" - představte si například Javascript/DOM aplikaci, která místo klasického souboru GET/POST proměnných z formuláře odesílá na server již hotový XML dokument...není tato představa lákavá? Pokud si osvojíte pokročilé techniky práce s XML v moderních prohlížečích, o kterých bude postupně řeč v dalších dílech tohoto seriálu, pak vám jistě nebude realizace této představy dělat velké problémy.

Jak by vypadalo vytváření XML dokumentu "od píky"? V první řadě by bylo nutné vložit kořenový element - toho bychom dosáhli uvedením jména kořenového elementu v druhém parametru metody createDocument(), ale stejný efekt by mělo vytvoření kořenového elementu samostatně a vložení do dokumentu:

var root = xmlDoc.createElement(`korenovy-element`);
xmlDoc.appendChild(root);

A jak je to s objektem doctype? Ten lze vytvořit za pomoci metody createDocumentType() objektu implementation. Metoda má 3 parametry - qualifiedName (kvalifikované jméno kořenového elementu), publicId (veřejný identifikátor) a systemId (systémový identifikátor).

var doctype = document.implementation.createDocumentType(`root-element`, ``, `doctype.dtd`);

Načtení XML dokumentu v MSIE - ActiveX

Vytvoření objektu DOM XML dokumentu a jeho načtení z externího zdroje umožňuje samozřejmě i Microsoft Internet Explorer od verze 5.0. Nevystačíme si však se standardním DOM rozhraním, jehož implementace v MSIE není na potřebné úrovni. Místo toho je potřeba vytvořit ActiveX objekt pomocí proprietální syntaxe. Samotnou práci s DOM XML dokumentem má na starosti MSXML parser, který se ovšem ve spojení s prohlížečem Microsoft Internet Explorer vyskytuje v několika verzích. Ukážeme si zápis, který funguje od nejnižší možné verze MSXML parseru, která byla distribuována s IE 5.0.

Objekt typu DOM XML dokument, analogický s tím, který jsme pomocí DOM metody createDocument() vytvářeli v Mozille, vznikne díky následujícímu kódu:

var xmlDoc = new ActiveXObject(`Microsoft.XMLDOM`);

Nyní existují dvě možnosti, které ošetřují načtení XML dokumentu. První je nastavení vlastnosti async na hodnotu false - tato vlastnost určuje, jestli je provedeno asynchronní načtení XML dokumentu, nebo nikoliv. Výchozí hodnotou je true - tato hodnota říká, že načítání XML dokumentu nijak neovlivní další běh skriptu, který nečeká, až se XML dokument kompletně načte. Nastavení na false má za následek pozdržení běhu skriptu až do té doby, než se XML dokument načte. Bezprostředně pak můžeme bez problému volat funkci, která zpracovává XML dokument, jak ukazuje následující kód.

xmlDoc.async = false;
xmlDoc.load(`cesta/k/xml/dokumentu.xml`);
zpracujXMLdokument();

Samotné načtení dokumentu zajišťuje názvem, funkcí i parametrem identická metoda load() stejně, jako v Mozille. Pokud je stažení XML dokumentu asynchronní, zřejmě budeme potřebovat obslužnou funkci zpracovávající XML dokument spouštět až po úplném načtení dokumentu. Bohužel v IE nemůžeme asociovat ovladač s událostí load, jelikož objekt DOM XML dokumentu ji nezná. Tento objekt však v IE disponuje vlastností readyState, jejíž hodnotou je vždy aktuální stav načtení XML DOM dokumentu reprezentovaný číslem od 1 do 4:

  1. LOADING - probíhá načítání souboru z externího zdroje
  2. LOADED - načtení souboru bylo dokončeno, probíhá parsování dat, ale zatím není ani částečně přístupná DOM reprezentace
  3. INTERACTIVE - některá data byla již rozparsována, DOM reprezentace je částečně přístupná, v každém případě však jen pro čtení
  4. COMPLETED - dokument byl kompletně načten a rozparsován, je plně k dispozici

K readyState se váže vlastnost onreadystatechange, pomocí které můžeme připojit ovladač události, která nastane při změně stavu načtení. A právě tyto dvě vlastnosti využijeme pro indikaci načtení XML dokumentu. Idea je postavena na odchytávání každé změny stavu načtení - přitom testujeme aktuální hodnotu readyState a pokud je tato hodnota 4 (COMPLETED), lze zavolat zpracovávací funkci.

xmlDoc.onreadystatechange = stateControl
xmlDoc.load(`cesta/k/xml/dokumentu.xml`);

function stateControl() {
	if(xmlDoc.readyState==4) zpracujXMLdokument();
}

Hrátky s readyState mohou být samozřejmě i propracovanější - při každé změně stavu načtení můžete například měnit "čekací" informaci (obrázek, animaci...), což může vypadat velice efektně. U drobných XML dokumentů, které asi budete chtít načítat nejčastěji, se zřejmě ale bez podobných efektů obejdete (přece jen, tyto rychlé změny stavu by si uživatelé asi moc neužili :-).

Bonus - jak obejít chybu vlastnosti childNodes v IE

Nyní už tedy víte, jak načíst XML dokument v IE 5+ a Mozille. Při práci s XML dokumentem pomocí DOM rozhraní můžete občas narazit na chybu, která se vyskytuje v některých verzích IE 5 (s největší pravděpodobností se jedná o chybu určité verze MSXML parseru). Chyba se projevuje "zkolabováním" skriptu při práci s kolekcí childNodes (tato vlastnost vrací všechny dětské nody určitého elementu). I když element obsahuje dětské uzly, childNodes vrátí null. Jako přídavek k dnešnímu dílu vám ukážu způsob, jak tuto nepříjemnou chybu obejít.

Celý problém řeší funkce, kterou jsem nazval getXMLchildNodes(). Funkce má 2 parametry - XMLnode, jehož kolekci childNodes potřebujeme získat, a logickou proměnnou isColl. Tato proměnná nabývá hodnoty:

  • true, pokud výsledný objekt bude třídy collection (analogie k rozhraní NodeList) s metodami item() a vlastností length
  • false, pokud se bude jednat o pole (tj. prvky můžeme volat pomocí indexu a stejně tak máme k dispozici vlastnost length).

Zde je kompletní kód.

function getXMLchildNodes(XMLnode, isColl) {
	if(XMLnode.childNodes) {
		return XMLnode.childNodes;
	} else {
		var aktChild = XMLnode.firstChild;
		var XMLchildNodes = new Array();
		
		while(aktChild) {
			XMLchildNodes[XMLchildNodes.length] = aktChild;
			aktChild = aktChild.nextSibling;
		}
		
		if(isColl) XMLchildNodes = new collection(XMLchildNodes);
		return XMLchildNodes;
	}
}

function collection(XMLchildNodes) {
	this.XMLchildNodes = XMLchildNodes;
	this.length = XMLchildNodes.length;
	this.item = item;
}

function item(i) {
	return this.XMLchildNodes[i];
}

Funkce nejprve otestuje, jestli vlastnost childNodes nevrací null - pokud ano, vrátí správný výsledek vlastnosti childNodes, pokud nikoliv, sestaví kolekci dětských uzlů jiným způsobem. Nejdříve vyhledá první dítě uzlu (firstChild) a poté cyklem while prochází další sourozence, než dojde na konec. Poté vrátí (dle hodnoty indikátoru isColl) buď vytvořený objekt třídy collection, nebo prosté pole dětských uzlů.

Použití funkce je jednoduché. Kdykoliv potřebujete bezpečně najít dětské uzly určitého elementu v DOM XML dokumentu, místo vlastnosti childNodes použijete funkci getXMLchildNodes(). Předáte jí objekt příslušného elementu a true/false v závislosti na způsobu, jakým jste zvyklí pracovat s kolekcí childNodes. Pokud k ní vždy přistupujete jako k poli (pomocí indexů), uveďte false, pokud používáte (v souladu se standardem DOM) metodu item(), použijte true. Podívejte se na konkrétní ukázky použití ve skriptu:

Původní kód:

var deti = elem.childNodes;
var treti_dite = deti.item(2);

Bezpečný kód:

var deti = getXMLchildNodes(elem, true);
var treti_dite = deti.item(2);

Tolik tedy o načtení XML dokumentu pomocí kombinace Javascript/DOM(/ActiveX). Přístě opět pokročíme a ukážeme si možné způsoby interakce DOM XML dokumentu s "prostředím". Díky tomu budeme schopni řádově zvýšit inteligenci našich Javascriptových aplikací založených na XML.

Diskuze (3) Další článek: Další nabídka ADSL od SkyNetu

Témata článku: Software, Microsoft, Programování, Internet Explorer, Určitý objekt, Dokončené dílo, Root, Nejnižší třída, Item, Nepříjemná vlastnost, IE 11, Doma, Code, Kompletní kód, První dítě, Pre, Element, XML, Stejný efekt, IE 10, Teorie


Určitě si přečtěte

Loopwheels znovu vymyslelo kolo. Místo drátů má v ráfcích kompozitové pružiny, které vylepší komfort jízdy

Loopwheels znovu vymyslelo kolo. Místo drátů má v ráfcích kompozitové pružiny, které vylepší komfort jízdy

** Proč vymýšlet kolo? Protože ho lze vymyslet lépe! ** Kola Loopwheels nabízejí integrované odpružení ** Cílem je poskytnout pohodlnější a klidnější jízdu

Karel Kilián | 14

Inteligentní akvárium Bluenero se o rybičky postará samo

Inteligentní akvárium Bluenero se o rybičky postará samo

** Chcete chovat akvarijní rybičky, ale nemáte čas se o ně starat? ** Chytré akvárium je samo nakrmí a postará se o jejich komfort ** Projekt Bluenero zatím sbírá finance na Indiegogo

Karel Kilián | 20

Porno insider: Jak virtuální realita vstupuje do filmů pro dospělé

Porno insider: Jak virtuální realita vstupuje do filmů pro dospělé

** Pornografie údajně představuje třetinu internetové obsahu a je technologický tahounem ** Do erotického obsahu postupně zasahuje i virtuální realita ** Kromě vizuálního vjemu se pracuje také na virtuálním uspokojení toho hmatového

Jan Dudek | 29

Nový iPhone a další novinky Applu: sledujte, na co se zase budou stát fronty

Nový iPhone a další novinky Applu: sledujte, na co se zase budou stát fronty

** Apple dnes představuje nové produkty v čele s novými iPhony ** Nemusí zůstat jen u telefonů, čekají se i další novinky ** Úvodní přednáška začíná v 19:00 našeho času

David Polesný | 57


Aktuální číslo časopisu Computer

Jak vytvořit a spravovat vlastní web

Velký test herních klávesnic a DVB-T2 tunerů

Vše o formátu RAW

Vybíráme nejlepší základní desku