Znění hlášky v jednotlivých parserech
Každý parser popisuje stejnou chybu jinými slovy. Java hlásí Content is not allowed in prolog, libxml2 (PHP, xmllint) Start tag expected nebo XML declaration allowed only at the start of the document, .NET Data at the root level is invalid. Hlášky v tabulce vznikly z ukázek níže:
Prolog je v terminologii XML všechno před kořenovým elementem: deklarace, komentáře,
DOCTYPE a instrukce pro zpracování. Samotný text tam být nesmí a deklarace
<?xml … ?> smí být jen na prvním místě v souboru.
Příčiny a opravy
Text před deklarací
Notice: Undefined index: id in /var/www/export.php on line 12
<?xml version="1.0" encoding="UTF-8"?>
<objednavky>
<objednavka cislo="2026-117"/>
</objednavky> <?xml version="1.0" encoding="UTF-8"?>
<objednavky>
<objednavka cislo="2026-117"/>
</objednavky>
Nejčastěji jde o varování nebo chybu, kterou skript vypsal do stejného výstupu jako XML
(typicky Notice nebo Warning v PHP), o log nebo o kus HTML. Oprav
příčinu výpisu, ne XML — a varování posílej do logu, ne do odpovědi.
Prázdný řádek nebo mezera před deklarací
<?xml version="1.0" encoding="UTF-8"?>
<objednavky>
<objednavka cislo="2026-117"/>
</objednavky> <?xml version="1.0" encoding="UTF-8"?>
<objednavky>
<objednavka cislo="2026-117"/>
</objednavky>
Stačí jediný prázdný řádek nebo mezera. V PHP ho často přidá prázdný řádek za
?> ve vloženém souboru nebo mezera před <?php. Java
v tomto případě hlásí The processing instruction target matching "[xX][mM][lL]" is not
allowed: deklaraci uprostřed textu považuje za instrukci pro zpracování se zakázaným
jménem xml.
BOM načtený jako znak do řetězce
<?xml version="1.0" encoding="UTF-8"?>
<objednavky>
<objednavka cislo="2026-117"/>
</objednavky> <?xml version="1.0" encoding="UTF-8"?>
<objednavky>
<objednavka cislo="2026-117"/>
</objednavky>
BOM (byte order mark, bajty EF BB BF) na začátku souboru v UTF-8 je povolený
a parser, který čte bajty, ho přeskočí. Potíž nastane, když program soubor nejdřív přečte do
řetězce a BOM v něm zůstane jako znak U+FEFF. Java (StringReader)
a .NET (LoadXml, XDocument.Parse) pak hlásí chybu na řádku 1,
sloupci 1, přestože v editoru žádný znak nevidíš. Python a libxml2 stejný řetězec přijmou.
Jak chybu najít
- Podívej se na pozici v hlášce. Line 1, position 1 nebo line 1, column 0 znamená, že problém je hned na začátku — nejspíš BOM nebo text před deklarací.
-
Neviditelné znaky ukáže hexadecimální výpis:
xxd soubor.xml | head -1na Linuxu a macOS, nebo hexdump v prohlížeči. BOM vypadá jakoef bb bf. -
Když XML přichází z API, ulož si přesnou odpověď do souboru (
curl -o odpoved.xml …) a teprve tu zkoumej — v logu aplikace se začátek odpovědi snadno ztratí. - Vlož dokument do validátoru, který zvýrazní řádek s chybou.
Oprava v kódu
Nejspolehlivější je nepřevádět XML na řetězec vůbec: soubor nebo odpověď předej parseru jako bajty (stream). Parser pak sám rozpozná BOM i kódování podle deklarace. Když řetězec máš, odstraň z jeho začátku BOM a bílé znaky:
// Nejlepší je předat parseru bajty: BOM i kódování si vyřeší sám.
Document doc = builder.parse(Files.newInputStream(path));
// Když už máš XML v řetězci, odstraň BOM a bílé znaky před <?xml.
String clean = xml.replaceFirst("^[\\uFEFF\\s]+", "");
Document doc = builder.parse(new InputSource(new StringReader(clean))); # utf-8-sig zahodí BOM, lstrip() prázdné řádky před deklarací
with open(path, encoding="utf-8-sig") as f:
root = ET.fromstring(f.read().lstrip()) $xml = preg_replace('/^(\xEF\xBB\xBF|\s)+/', '', $xml);
$doc = simplexml_load_string($xml); // XDocument.Load(cesta) si BOM poradí sám. Z řetězce ho odstraň:
var doc = XDocument.Parse(text.TrimStart('\uFEFF', ' ', '\t', '\r', '\n')); Ořezávání je jen záplata. Text před deklarací (varování PHP, log) je znamení, že se do výstupu dostává něco, co tam nepatří — oprav i zdroj.
Související
- Kódování znaků, BOM a deklarace v kapitole Jak funguje XML.
- Extra content at the end of the document — deklarace uprostřed souboru po spojení dvou dokumentů.
- Premature end of file — když místo XML přijde HTML stránka nebo JSON.
- Přehled všech chybových hlášek.