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

Lze přímo v prohlížeči převádět XML v textové podobě na DOM XML dokument a naopak? Odpověď zní: ano, jde to, a není to nijak složité. V dnešním dílu si ukážeme, jak na to.

Pokud chceme, aby naše klientské JS/DOM aplikace založené na XML pracovaly efektivně, dříve nebo později budeme postaveni před problém konverze XML dokumentu z jeho textové reprezentace (stringu) do DOM objektu a obráceně. Typickým příkladem jsem vstupy a výstupy formulářů - potřebujeme například, aby uživatel mohl vkládat XML dokument do textového pole (textarea), nicméně s tímto dokumentem chceme posléze pracovat jako s DOM objektem. Stejně tak při odeslání XML dokumentu, se kterým manipulujeme pomocí DOM rozhraní, prostřednictvím formuláře, nutně narazíme na problém konverze na řetězec. Oba dva typy "transmutace" XML jsou v prohlížečích Mozilla a Microsoft Internet Explorer možné.

Vytvoření DOM XML dokumentu z textového řetězce

Mozilla

Pro vytvoření objektu DOM XML dokumentu v Mozille můžeme použít vestavěný XML Parser. V Javascriptu objekt parseru vytvoříme voláním konstruktoru DOMParser(). Objekt disponuje metodou parseFromString(). Metoda má dva parametry - prvním je textový řetězec (string) XML dokumentu, který hodláme načíst. Druhým parametrem je typ (contentType), jenž nabývá hodnoty text/xml. Metoda vrací objekt typu DOM XML dokument.

var Parser = new DOMParser();
var xmlDoc = Parser.parseFromString(`<root>data</root>`, `text/xml`);

Microsoft Internet Explorer

Při vytváření DOM XML dokumentu z textového řetězce v IE musíme postupovat podobně, jako při načítání externího XML dokumentu. Napřed je tedy nutné vytvořit objekt DOM XML dokumentu pomocí ActiveX. Samotné načtení ze stringu pak zajišťuje metoda loadXML(), jejímž jediným parametrem je řetězec, který reprezentuje XML dokument.

var xmlDoc = new ActiveXObject(`Microsoft.XMLDOM`);
xmlDoc.loadXML(`<root>data</root>`);

Vytvoření textového řetězce z DOM XML dokumentu (DOM nodu)

Mozilla

Pro vytvoření textové reprezentace DOM XML dokumentu existuje v Mozille objekt XML Serializer. Použití je analogické, jako u XML Parseru - objekt vzniká pokud zavoláme konstruktor XMLSerializer(). Pak lze použít metodu serializeToString(), které předáme jako jediný parametr objekt DOM XML dokumentu. Kromě samotného DOM XML dokumentu lze Serializéru předávat jakýkoliv jiný DOM Node. Lze tedy převést na řetězec v podstatě kteroukoliv vybranou část XML dokumentu (parciální strom, nebo i koncový nód bez potomků).


var node = xmlDoc.getElementsByTagName(`root`).item(0);
var XS = new XMLSerializer();
var retezec = XS.serializeToString(node);

Microsoft Internet Explorer

V Microsoft Internet Exploreru není nutné Kvůli serializaci DOM nodů na řetězec vytvářet žádné nové objekty. Každý DOM Node má v MSXML parseru vlastnost xml, která vrací textovou reprezentaci příslušného uzlu. Výsledek a rozsah použití je tedy stejný jako v Mozille.

var retezec = node.xml;

Při serializaci DOM nodu se ve výsledném textovém řetězci může vyskytnout rozdíl mezi Mozillou a IE. V případě, že je na řetězec převáděn kořenový element (documentElement) dokumentu, v Mozille chybí počáteční a koncový tag tohoto elementu (v řetězci se objeví všichni potomci kořenového elementu). Pokud potřebujeme, aby řetězec byl v IE a Mozille stejný, je řešením serializace objektu DOM XML dokumentu, nikoliv pouze kořenového elementu.

Další problém se může vyskytnout při použití jiného kódování než UTF-8. MSXML parser v IE převádí všechny XML dokumenty z jejich originálního kódování do Unicode a přitom je vypuštěna případná explicitní deklarace kódování v hlavičce XML documentu. Mozilla tuto hlavičku zachovává v původní podobě a kódování nemění. Další důvod, proč preferovat univerzální kódování UTF-8.

XML a formuláře

Přistupme nyní k praktické ukázce. Následující příklad demonstruje použití XML dokumentu jakožto nositele dat pro formulář. Nositel má v tomto případě "obousměrný" význam - tentýž XML dokument zajistí jak přenos dat pro vytvoření formuláře ze serveru do klientské aplikace, tak i (po případné modifikaci při změně položek uživatelem ve formuláři) z aplikace zpět na server. Vytvoření formuláře zajistí mocná kombinace Javascript/DOM na pokyn uživatele, takže odpadne vytváření a načítání nové stránky s formulářem na straně serveru. Server pouze posílá XML soubor, který také po odeslání přijímá. Jedná se tedy o poměrně efektivní cestu, jak přenést práci ze serveru na klientský browser.

XML dokument s daty pro vytvoření formuláře je velice jednoduchý.

<formdata>
	<jmeno>Jakub</jmeno>
	<prijmeni>Havel</prijmeni>
	<ulice>Xxxxxxx</ulice>
	<cp>1234</cp>
	<mesto>Praha</mesto>
	<telefon>123456789</telefon>
</formdata>

Funkční příklad si můžete vyzkoušet prakticky. Ukažme si tedy jednotlivé části skriptu. První část obsahuje pouze inicializační proměnné - cestu k načítanému XML souboru, cestu ke skriptu, na který má být formulář odesílán a asociativní pole s popisy položek.

var formXmlSrc = `form.xml`;
var formXmlDst = `nejaky/script.php`;

var LABELS = new Array();
LABELS[`jmeno`] = `Vase jmeno:`;
LABELS[`prijmeni`] = `Vase prijmeni:`;
LABELS[`ulice`] = `Ulice:`;
LABELS[`cp`] = `Cislo popisne:`;
LABELS[`mesto`] = `Mesto:`;
LABELS[`telefon`] = `Telefonni cislo:`;

Další částí je funkce pro načtení XML dokumentu v IE5+ a Mozille. Jedná se o mírně upravenou funkci od P.P.Kocha. Souvisejícími podrobnostmi jsme se zabývali dva díly zpět.

var xmlDoc;

function initXML() {
	if (document.implementation && document.implementation.createDocument) {
		xmlDoc = document.implementation.createDocument("", "", null);
		xmlDoc.onload = createForm;
	} else if (window.ActiveXObject) {
		xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
		xmlDoc.onreadystatechange = function () {
			if (xmlDoc.readyState == 4) createForm();
		}
 	} else {
		alert(`Your browser can\`t handle this script`);
		return;
	}
	xmlDoc.load(formXmlSrc);
}

Pak následuje funkce getXMLtext(), která zapouzdřuje převod DOM uzlů na textové řetězce.

function getXMLtext(node) {
	if(node.xml) {
		return node.xml;
	} else if(XMLSerializer()) {
		var XS = new XMLSerializer();
		return XS.serializeToString(node);
	}
}

Další v pořadí je funkce pro vytvoření formuláře a vyplnění daty z načteného XML souboru.

function createForm() {
	var children = xmlDoc.documentElement.childNodes;
	var form = document.createElement(`form`);
	form.id = `xmlform`;
	form.action = formXmlDst;
	form.method = `post`;
	form.onsubmit = sendXML;
	
	for(i=0; i<children.length; i++) {
		if(children[i].nodeType!=1) continue;
		
		var controlNode, valueNode, name;
		controlNode = document.createElement(`input`);
		controlNode.type = `text`;
		name = children[i].nodeName;
		controlNode.name = name;
		valueNode = children[i].firstChild;
		if(valueNode) {
			controlNode.value = valueNode.data;
		}
			labelNode = document.createElement(`label`);
			labelText = document.createTextNode(LABELS[name]);
			labelNode.appendChild(labelText);
			labelNode.appendChild(controlNode);
			
		var block = document.createElement(`div`);
		block.appendChild(labelNode);
		form.appendChild(block);
	}
	
	var submitNode = document.createElement(`input`);
	submitNode.type = `submit`;
	form.appendChild(submitNode);
	document.links[0].style.display = `none`;
	document.body.appendChild(form);
}

Poslední funkce sendXML() se spouští při odeslání formuláře. Funkce v cyklu zkontroluje všechny formulářové položky a jejich aktuální hodnotu vloží do XML dokumentu na místo starých hodnot. Poté odstraní všechny formulářové položky a vytvoří skryté textové pole, do kterého se vloží výsledný XML dokument jako řetězec, který je také vypsán pomocí alert(). Samotné odeslání v našem případě neproběhne, protože funkce sendXML(), která je ovladačem události submit, odeslání pomocí návratové hodnoty false přeruší (důvod je pouze ten, že ukázka nemá existující serverový skript, na který by bylo možné data odesílat).

function sendXML() {
	var form = document.forms[`xmlform`];
	var controls = form.elements;
	for(i=0; i<controls.length; i++) {
		if(controls[i].type==`submit`) continue;
		var item = xmlDoc.getElementsByTagName(controls[i].name)[0];
		item.firstChild.data = controls[i].value;
	}
	
	for(i=controls.length-1; i>=0; i--) {
		controls[i].parentNode.removeChild(controls[i]);
	}
	var hiddenXml = document.createElement(`input`);
	hiddenXml.type = `hidden`;
	hiddenXml.name = `formdata-xml`;
	hiddenXml.value = getXMLtext(xmlDoc);
	form.appendChild(hiddenXml);
	alert(hiddenXml.value);
	return true;
}

Důvod ke smazání všech starých položek formuláře před odesláním je jednoduchý - všechna data obsahuje XML dokument, pro který je vytvořeno skryté pole, ostatní položky nejsou potřeba.

Aplikaci by bylo možné různě modifikovat - například by mohla kontrolovat, které údaje se změnily, a poté sestavit XML dokument pouze se změněnými položkami - v případě nulové změny by k odeslání formuláře vůbec nedošlo. Záleží jen na zadání, potřebách a schopnostech.

Abychom však docílili opravdové elegance, něco tomuto řešení chybí - tím slabým místem je odesílání formuláře. Kvůli odeslání se musí načítat nová stránka. Řešením by mohlo být vytvoření dalšího formuláře např. ve skrytém rámu, nebo nasměřování výsledné stránky zpracovávacího serverového skriptu do tohoto rámu (pomocí target u formuláře), nicméně jistě cítíte, že to není "úplně ono". Pak tedy přišel čas prozradit, že existuje ještě řádově pokročilejší způsob komunikace klient-server na bázi XML, než je ten dnes popsaný. Na ten se však podíváme až příště.

Diskuze (2) Další článek: Český hudební trh v roce 2002 opět zaznamenal meziroční propad

Témata článku: Software, Microsoft, Programování, Internet Explorer, Unicode, Alert, Vase, Doma, Block, Starý typ, Root, Item, Starý telefon, Code, Hidden, Textové pole, Textový řetězec, Element, Elsa, XML, Pre, Teorie, Výsledné dílo


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

Portál občana už funguje. Na státní web vypadá až překvapivě použitelně

Portál občana už funguje. Na státní web vypadá až překvapivě použitelně

** Portál občana už funguje, vyřídíte na něm první požadavky ** Funkce se budou postupně rozšiřovat ** Web je docela moderní a přehledný

David Polesný | 66

Externí SSD se může hodit. Je rychlé, malé zvenku, velké uvnitř a cena už se snese

Externí SSD se může hodit. Je rychlé, malé zvenku, velké uvnitř a cena už se snese

** Vyzkoušeli jsme rychlé externí SSD Samsung T5 ** Externí SSD je lepší než flešky i velké plotnové disky, většímu rozšíření doposud bránila především cena ** Samsung T5 zvládne i chytré šifrování a připojení k mobilu

David Polesný | 27

Astronomové objevili daleko za Plutem objekt s extrémní dráhou. Může ukazovat na existenci planety Devět

Astronomové objevili daleko za Plutem objekt s extrémní dráhou. Může ukazovat na existenci planety Devět

** Astronomové objevili daleko za Neptunem těleso 2015 TG387 ** Okolo Slunce se pohybuje po extrémně protáhlé dráze ** Jeho dráha může ukazovat na existenci planety Devět

Petr Kubala | 10

Osudová havárie Concordu: Před 18 lety přišel konec nadzvukových dopravních letadel

Osudová havárie Concordu: Před 18 lety přišel konec nadzvukových dopravních letadel

** Concorde byl nejrychlejším dopravním letadlem ** Atlantik dokázal přeletět za cca 3 až 3,5 hodiny ** Před osmnácti lety tragická havárie provoz těchto letadel prakticky ukončila

David Polesný, Jiří Černý | 37

Zapomeňte na kabely, vědci už mají prototyp 120kW bezdrátové nabíječky pro elektromobily

Zapomeňte na kabely, vědci už mají prototyp 120kW bezdrátové nabíječky pro elektromobily

** Vědci představili prototyp výkonné bezdrátové nabíječky pro elektromobily ** I přes vysoký výkon se pyšní vysokou efektivitou ** Bude budoucnost nabíjení elektromobilů bezdrátová?

Karel Javůrek | 44

Užijte si poslední změny času: Už od března 2019 můžeme mít trvale letní čas

Užijte si poslední změny času: Už od března 2019 můžeme mít trvale letní čas

** Evropská komise přijala legislativní návrh na zrušení střídaní času ** Možná tak v březnu 2019 přesuneme ručičky hodinek naposledy ** Od toho okamžiku bude permanentně platit letní čas

Karel Kilián | 106


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