Content is not allowed in prolog: příčina a oprava

Parser našel před deklarací <?xml … ?> něco, co tam nesmí být: text, prázdný řádek, mezeru nebo neviditelný znak BOM. Deklarace musí stát úplně na začátku souboru. Oprava je smazat všechno před ní, v kódu nejčastěji předat parseru soubor jako bajty, ne jako řetězec.

Autor: Aktualizováno

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:

Parser Hláška Kdy
libxml2 2.13 a novější PHP (DOM, SimpleXML), xmllint, Python lxml, validátor na XML.cz Start tag expected, '<' not found Text před deklarací
XML declaration allowed only at the start of the document Prázdný řádek nebo mezera před deklarací
projde bez chyby BOM načtený jako znak do řetězce
Java (Xerces) DocumentBuilder, SAXParser, JAXB, Spring, Maven Content is not allowed in prolog. Text před deklarací, BOM načtený jako znak do řetězce
The processing instruction target matching "[xX][mM][lL]" is not allowed. Prázdný řádek nebo mezera před deklarací
Python (expat) xml.etree.ElementTree, minidom syntax error: line 1, column 0 Text před deklarací
XML or text declaration not at start of entity: line 2, column 0 Prázdný řádek nebo mezera před deklarací
projde bez chyby BOM načtený jako znak do řetězce
.NET XmlDocument, XDocument, XmlReader Data at the root level is invalid. Line 1, position 1. Text před deklarací, BOM načtený jako znak do řetězce
Unexpected XML declaration. The XML declaration must be the first node in the document, and no whitespace characters are allowed to appear before it. Line 2, position 3. Prázdný řádek nebo mezera před deklarací
Chrome 151+ DOMParser, zobrazení XML souboru Unexpected characters outside the root element: N Text před deklarací
Invalid processing instruction: <?xml Prázdný řádek nebo mezera před deklarací
Firefox DOMParser, zobrazení XML souboru syntax error Text před deklarací
XML or text declaration not at start of entity Prázdný řádek nebo mezera před deklarací

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í

Chybně
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>
Opraveno
<?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í

Chybně: první řádek je prázdný

<?xml version="1.0" encoding="UTF-8"?>
<objednavky>
  <objednavka cislo="2026-117"/>
</objednavky>
Opraveno
<?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

Chybně: na začátku je neviditelný znak U+FEFF
<?xml version="1.0" encoding="UTF-8"?>
<objednavky>
  <objednavka cislo="2026-117"/>
</objednavky>
Opraveno
<?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 -1 na Linuxu a macOS, nebo hexdump v prohlížeči. BOM vypadá jako ef 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:

Java
// 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)));
Python
# 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())
PHP
$xml = preg_replace('/^(\xEF\xBB\xBF|\s)+/', '', $xml);
$doc = simplexml_load_string($xml);
C#
// 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í