XML a JSON v JavaScriptu

Prohlížeč má vestavěný XML parser, XPath i převod zpět na text — bez jediné knihovny. Kapitola ukazuje, jak XML v JavaScriptu načíst, poznat chybu zápisu, vyhledat v něm data, poradit si se jmennými prostory a jak prohlížeč zobrazuje samotné XML soubory.

Autor: Aktualizováno

Načtení XML: DOMParser

Text s XML převede na dokument objekt DOMParser. Výsledek je stejný Document, jaký znáš z HTML stránky, takže na něm fungují známé metody jako getElementsByTagName, getAttribute nebo textContent.

JavaScript
const text = `<objednavka cislo="2026-117">
  <polozka mnozstvi="2">Hrnek</polozka>
  <polozka mnozstvi="1">Talíř</polozka>
</objednavka>`;

const doc = new DOMParser().parseFromString(text, 'application/xml');
const root = doc.documentElement;

console.log(root.getAttribute('cislo'));                  // "2026-117"
for (const polozka of root.getElementsByTagName('polozka')) {
  console.log(polozka.textContent, polozka.getAttribute('mnozstvi'));
}

Druhý argument je typ obsahu a rozhoduje o tom, jaký parser se použije. Pro XML to musí být application/xml (nebo text/xml, případně image/svg+xml). S text/html by prohlížeč text četl jako HTML: chyby by tiše opravil, názvy elementů převedl na malá písmena a samo-uzavírací značky by nerozpoznal.

ÚkolAPI v prohlížeči
Text → dokumentnew DOMParser().parseFromString(text, "application/xml")
Kořenový elementdoc.documentElement
Elementy podle jménagetElementsByTagName(), getElementsByTagNameNS(), querySelector()
Atributy a textgetAttribute(), setAttribute(), textContent
Dotaz XPath 1.0doc.evaluate(výraz, uzel, resolver, typ, null)
Nový dokumentdocument.implementation.createDocument(ns, "koren", null)
Dokument → textnew XMLSerializer().serializeToString(doc)

Jak poznat chybu zápisu

DOMParser při chybě nevyhodí výjimku. Vrátí dokument, ve kterém je místo dat element <parsererror> s popisem chyby. Kdo to nekontroluje, pracuje pak s prázdnými výsledky a neví proč. Kontrola proto patří hned za každé parsování:

JavaScript
function parseXml(text) {
  const doc = new DOMParser().parseFromString(text, 'application/xml');
  const error = doc.querySelector('parsererror');
  if (error) throw new Error(error.textContent);
  return doc;
}

parseXml('<a><b></a>');  // Error: … Unexpected closing tag: a != b …

Text hlášky se liší podle prohlížeče: Chrome od verze 151 používá parser napsaný v Rustu, Safari knihovnu libxml2 a Firefox vlastní parser. Význam hlášek vysvětluje kapitola Jak funguje XML. Funkci parseXml používají i další ukázky na této stránce.

Načtení souboru ze serveru nebo z disku

Soubor ze serveru stáhni přes fetch a text předej parseru. Soubor, který vybral uživatel, přečteš metodou file.text() — nikam se neodesílá, všechno proběhne v prohlížeči.

JavaScript
// soubor ze serveru
const response = await fetch('/data/objednavky.xml');
const doc = parseXml(await response.text());

// soubor, který uživatel vybral v <input type="file">
const file = input.files[0];
const doc2 = parseXml(await file.text());

Starší XMLHttpRequest umí XML rozparsovat sám a výsledek vrátí ve vlastnosti responseXML; v novém kódu je jednodušší fetch s DOMParserem. Při čtení z jiné domény platí běžná pravidla CORS.

Vytvoření XML a převod zpět na text

Nový dokument vytvoříš přes document.implementation.createDocument, elementy přes createElementNS a na text ho převede XMLSerializer. Oproti skládání textu z řetězců má tahle cesta velkou výhodu: znaky < a & v datech se escapují samy.

JavaScript
const NS = 'http://example.cz/faktura';
const doc = document.implementation.createDocument(NS, 'faktura', null);

const cislo = doc.createElementNS(NS, 'cislo');
cislo.textContent = 'FV2026-042 & spol.';      // & se při uložení zapíše jako &amp;
doc.documentElement.append(cislo);

const xml = new XMLSerializer().serializeToString(doc);
// <faktura xmlns="http://example.cz/faktura"><cislo>FV2026-042 &amp; spol.</cislo></faktura>

XMLSerializer nepřidá deklaraci <?xml …?> a výstup neodsazuje. Deklaraci si podle potřeby připoj sám; pro čitelný výstup použij formátovač.

Bezpečnost: text z XML nevkládej do stránky přes innerHTML. Soubor od cizího odesílatele může v textu nést HTML se skriptem. Použij textContent, které text vloží jako text.

Serializace XML

Při převodu XML stromu na text (serializaci) knihovna zapíše zvláštní znaky podle pravidel XML, například ampersand jako &amp;. Zápis zpět nemusí zachovat původní prefixy, odsazení, CDATA nebo pořadí atributů; testuj obsah a požadované kódování.

new XMLSerializer().serializeToString(doc);

DOM

DOMParser vrací Document se stromem uzlů. Pro jmenné prostory používej createElementNS a getElementsByTagNameNS; neporovnávej pouze prefix. Text vkládej přes textContent.

Streamové čtení XML

DOMParser načítá celý dokument; standardní rozhraní prohlížeče neposkytuje SAX parser pro čtení po událostech. V Node.js zvol streamový XML parser a zpracovávej data z createReadStream postupně po událostech. Při předávání výsledků dál čekej, až je výstup připraven přijmout; tomu se říká backpressure. JSON.parse také potřebuje celý text; velké JSON seznamy vyžadují jiný parser nebo formát po záznamech.

XPath: document.evaluate

Na složitější dotazy má prohlížeč vestavěný XPath. Metoda evaluate přijme výraz, výchozí uzel, funkci pro překlad prefixů, požadovaný typ výsledku a nepovinně objekt k opakovanému použití:

JavaScript
const result = doc.evaluate(
  '/objednavka/polozka[@mnozstvi > 1]',   // výraz XPath 1.0
  doc,                                    // uzel, od kterého se hledá
  null,                                   // resolver prefixů (bez jmenných prostorů null)
  XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
  null,
);
for (let i = 0; i < result.snapshotLength; i++) {
  console.log(result.snapshotItem(i).textContent);   // "Hrnek"
}

// jedna hodnota
doc.evaluate('count(//polozka)', doc, null, XPathResult.NUMBER_TYPE, null).numberValue;  // 2

// se jmenným prostorem: resolver převede prefix na URI
const resolver = (prefix) => (prefix === 'f' ? 'http://example.cz/faktura' : null);
doc.evaluate('//f:cislo', doc, resolver, XPathResult.STRING_TYPE, null).stringValue;

Prohlížeče umí jen XPath 1.0. Funkce z novějších verzí (například matches() nebo format-date()) skončí chybou. Výrazy pro jmenné prostory potřebují přiřazení prefixů k URI (resolver) i tehdy, když dokument používá výchozí jmenný prostor bez prefixu — v XPath 1.0 si pro něj vymysli vlastní prefix.

Jmenné prostory

Jakmile dokument používá jmenné prostory, hledej elementy podle URI jmenného prostoru a lokálního jména metodou getElementsByTagNameNS. Hledání podle prefixu (f:cislo) funguje jen náhodou — stejný dokument může mít jiný prefix nebo výchozí jmenný prostor bez prefixu a kód pak přestane fungovat.

JavaScript
const text = `<f:faktura xmlns:f="http://example.cz/faktura">
  <f:cislo>FV2026-042</f:cislo>
</f:faktura>`;
const doc = parseXml(text);
const NS = 'http://example.cz/faktura';

doc.getElementsByTagNameNS(NS, 'cislo')[0].textContent;  // "FV2026-042"
doc.getElementsByTagName('f:cislo').length;              // 1 — ale jen s tímhle prefixem
doc.querySelector('cislo');                              // najde, ale v jakémkoli jmenném prostoru

querySelector('cislo') element najde, protože selektor bez prefixu bere v úvahu jen lokální jméno. Neumí ale odlišit dva slovníky se stejným názvem elementu (třeba <nazev> zboží a <nazev> dodavatele), a proto se hodí jen pro dokumenty bez jmenných prostorů. Velikost písmen rozlišuje, stejně jako XML.

Validace proti XSD

Prohlížečové DOMParser nemá XSD validaci. Použij knihovnu, například xmllint ve WebAssembly jako nástroj XML.cz, nebo serverový validátor. Ověř podporovanou verzi XSD a zakázané externí zdroje.

Bezpečné nastavení parseru

Nezobrazuj nedůvěryhodné XML přes innerHTML. Serverové knihovny konfiguruj zvlášť proti externím entitám a DTD podle XXE. Omez velikost vstupu a čas zpracování. Bezpečné nastavení prohlížeče není nastavení Node.js.

Jak prohlížeč zobrazí samotný XML soubor

Když XML soubor otevřeš přímo v prohlížeči, záleží na tom, co obsahuje:

Co XML soubor obsahujeCo prohlížeč zobrazí
nic navícstrom elementů a nad ním upozornění, že soubor nemá styl
<?xml-stylesheet type="text/css" href="…"?>dokument naformátovaný podle CSS jako běžnou stránku
<?xml-stylesheet type="text/xsl" href="…"?>výsledek transformace XSLT — v Chromu jen do verze 157
chybu zápisuchybovou hlášku s číslem řádku místo obsahu

Styl připojuje instrukce pro zpracování <?xml-stylesheet?>. Varianta s CSS funguje dál, varianta s XSLT ale končí: Chrome od verze 158 (17. listopadu 2026) přestane XSLT podporovat, včetně objektu XSLTProcessor v JavaScriptu. Firefox a Safari odstranění plánují také. Kód, který XSLTProcessor používá, zachráníš knihovnou xslt-polyfill (libxslt ve WebAssembly), další náhrady najdeš v kapitole XSLT.

A co Node.js?

Node.js DOMParser, XMLSerializer ani document.evaluate nemá — jsou to rozhraní prohlížeče. Na serveru sáhni po knihovně: @xmldom/xmldom nabízí stejné DOM API jako prohlížeč, fast-xml-parser převádí XML rovnou na objekty JavaScriptu. Pro validaci proti XSD a XSLT se používají vazby na libxml2 nebo SaxonJS.

Načtení JSON

JSON parser vrací datovou strukturu, ne XML strom. Chyby syntaxe zpracuj jako chyby vstupu; data ověř také strukturálně.

const text = '{"jmeno":"Jana","vek":20}';
const data = JSON.parse(text);
console.log(data.jmeno);

Vytvoření JSON

Vytvoř hodnotu v paměti a nech její textový zápis na knihovně.

const data = { jmeno: 'Jana', vek: 20, aktivni: true };

Serializace JSON

Neskládej text ručně. Ověř přesnost čísel, reprezentaci dat a chování nečíselných hodnot.

const text = JSON.stringify(data, null, 2);

JSON Schema

Standardní knihovna neposkytuje plnou validaci JSON Schema. Vyber knihovnu s podporou požadované verze pravidel JSON Schema z oficiální dokumentace či katalogu. Základy a rozdíly verzí vysvětluje kurz JSON Schema.

Ukázka vyžaduje instalaci uvedeného balíčku. Kontrola format závisí na nastavení knihovny; validace nenahrazuje obchodní pravidla.

import { Validator } from '@cfworker/json-schema';
const schema = { type: 'object', properties: { vek: { type: 'integer' } }, required: ['vek'] };
const result = new Validator(schema, '2020-12').validate({ vek: 20 });
console.log(result.valid);

Dokumentace API

Příklady JSON vycházejí z oficiální dokumentace jazyka. Překlady typů, maximální hloubka a chování při chybě jsou vlastnosti knihovny, ne samotné syntaxe JSON.

JSON Schema: ověření skutečných vstupních dat

ESM ukázka v Node.js nebo aplikaci s bundlerem; npm install @cfworker/json-schema
import {Validator} from "@cfworker/json-schema";
const validator = new Validator({
  $schema: "https://json-schema.org/draft/2020-12/schema",
  type: "object", required: ["id"],
  properties: {id: {type: "string", pattern: "^[0-9]{3}$"}},
  additionalProperties: false
});
for (const text of ['{"id":"001"}', '{"id":1}', '{"id":"001","admin":true}']) {
  const result = validator.validate(JSON.parse(text));
  console.log(result.valid);
}

Výsledek je true, false, false. JSON.parse ověřilo všechny tři texty syntakticky; až schéma odmítlo číslo a neočekávané pole. V prohlížeči nelze holý import názvu npm balíčku použít bez bundleru či import mapy. Tento příklad spouštěj v Node.js jako .mjs nebo začleň do svého sestavení.

Schéma nevytváří oprávnění a nemění typy. Identifikátor 001 zůstává text. Pro práci se soubory a streamy navazuje Node.js / TypeScript kapitola.