Premature end of file: prázdná odpověď nebo data, která nejsou XML

Parser nedostal XML: soubor je prázdný, server místo dat vrátil HTML chybovou stránku, nebo API odpovědělo v JSON. Hláška pak mluví o konci souboru, chybějícím kořenovém elementu nebo o neuzavřené značce, která v tvém XML vůbec není. Před parsováním zkontroluj stavový kód, typ obsahu a to, že odpověď není prázdná.

Autor: Aktualizováno

Znění hlášky v jednotlivých parserech

Pro prázdný vstup hlásí Java Premature end of file, .NET Root element is missing, libxml2 (PHP, xmllint) Document is empty a Python no element found. HTML a JSON vyvolají hlášky, které na první pohled s příčinou nesouvisí:

Parser Hláška Kdy
libxml2 2.13 a novější PHP (DOM, SimpleXML), xmllint, Python lxml, validátor na XML.cz Document is empty Prázdný soubor nebo prázdná odpověď
Opening and ending tag mismatch: hr line 5 and body HTML chybová stránka místo XML
Start tag expected, '<' not found JSON místo XML
Java (Xerces) DocumentBuilder, SAXParser, JAXB, Spring, Maven Premature end of file. Prázdný soubor nebo prázdná odpověď
The element type "hr" must be terminated by the matching end-tag "</hr>". HTML chybová stránka místo XML
Content is not allowed in prolog. JSON místo XML
Python (expat) xml.etree.ElementTree, minidom no element found: line 1, column 0 Prázdný soubor nebo prázdná odpověď
mismatched tag: line 6, column 2 HTML chybová stránka místo XML
not well-formed (invalid token): line 1, column 0 JSON místo XML
.NET XmlDocument, XDocument, XmlReader Root element is missing. Prázdný soubor nebo prázdná odpověď
The 'hr' start tag on line 5 position 2 does not match the end tag of 'body'. Line 6, position 3. HTML chybová stránka místo XML
Data at the root level is invalid. Line 1, position 1. JSON místo XML
Chrome 151+ DOMParser, zobrazení XML souboru Unexpected end of stream: no root element found Prázdný soubor nebo prázdná odpověď
Unexpected closing tag: body != hr HTML chybová stránka místo XML
Unexpected characters outside the root element: { JSON místo XML
Firefox DOMParser, zobrazení XML souboru no root element found Prázdný soubor nebo prázdná odpověď
mismatched tag. Expected: </hr>. HTML chybová stránka místo XML
not well-formed JSON místo XML

Příčiny a opravy

Prázdný soubor nebo prázdná odpověď

Chybně: prázdný soubor
Opraveno
<?xml version="1.0" encoding="UTF-8"?>
<objednavky/>

Prázdný soubor vzniká, když export skončí chybou, ale soubor už byl založený, nebo když server vrátí stav 204 No Content či přesměrování, které klient nesleduje. Soubor jen s mezerami a prázdnými řádky dopadne stejně — Java i tu hlásí Premature end of file.

HTML chybová stránka místo XML

Chybně
<html>
<head><title>502 Bad Gateway</title></head>
<body>
<center><h1>502 Bad Gateway</h1></center>
<hr><center>nginx</center>
</body>
</html>
Opraveno
<?xml version="1.0" encoding="UTF-8"?>
<objednavky>
  <objednavka cislo="2026-117"/>
</objednavky>

Chybová stránka nginx (502, 503, 504), přihlašovací formulář nebo stránka s „údržbou“. HTML nemusí mít uzavřené značky jako <hr>, <br> nebo <meta>, takže XML parser skončí na první z nich. Hláška The element type "hr" must be terminated by the matching end-tag je proto spolehlivé znamení, že přišla HTML stránka, ne rozbité XML.

JSON místo XML

Chybně
{"objednavky": [{"cislo": "2026-117"}]}
Opraveno
<?xml version="1.0" encoding="UTF-8"?>
<objednavky>
  <objednavka cislo="2026-117"/>
</objednavky>

Mnoho API vrací JSON, pokud klient v hlavičce Accept nepožádá o application/xml, nebo vrací JSON jen u chybových odpovědí. Java hlásí Content is not allowed in prolog, protože první znak { nemůže být začátkem XML.

Jak chybu najít

  • Stáhni odpověď stejně, jak ji dostává aplikace, a ulož ji do souboru: curl -sS -D - -o odpoved.xml URL vypíše i stavový kód a hlavičky.
  • Zkontroluj hlavičku Content-Type. Pro XML bývá application/xml nebo text/xml, text/html znamená chybovou stránku.
  • Loguj začátek odpovědi (prvních 200 znaků), když parser selže. Z hlášky parseru samotné se obsah odpovědi nepoznáš.

Ošetření v kódu

Před parsováním zkontroluj stavový kód, typ obsahu a prázdnou odpověď. Chybová hláška pak řekne, co se skutečně stalo, místo Premature end of file:

Java (java.net.http)
HttpResponse<byte[]> res = client.send(request, HttpResponse.BodyHandlers.ofByteArray());
String type = res.headers().firstValue("Content-Type").orElse("");
if (res.statusCode() != 200) throw new IOException("HTTP " + res.statusCode() + ", " + type);
if (res.body().length == 0) throw new IOException("Prázdná odpověď");
if (!type.contains("xml")) throw new IOException("Nečekaný Content-Type: " + type);
Document doc = builder.parse(new ByteArrayInputStream(res.body()));
Python
with urllib.request.urlopen(url) as res:  # při HTTP 4xx a 5xx vyhodí HTTPError
    data = res.read()
head = data.lstrip(b"\xef\xbb\xbf \t\r\n")
if not head:
    raise ValueError("Prázdná odpověď")
if not head.startswith(b"<"):
    raise ValueError(f"Odpověď není XML: {data[:80]!r}")
root = ET.fromstring(data)
JavaScript
const res = await fetch(url);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const text = await res.text();
if (!text.trim()) throw new Error('Prázdná odpověď');
if (!text.trimStart().startsWith('<')) throw new Error(`Odpověď není XML: ${text.slice(0, 80)}`);
const doc = new DOMParser().parseFromString(text, 'application/xml');
PHP
$xml = file_get_contents($url);
if ($xml === false || trim($xml) === '') {
    throw new RuntimeException('Prázdná odpověď nebo chyba spojení');
}
libxml_use_internal_errors(true);
$doc = simplexml_load_string($xml);
if ($doc === false) {
    throw new RuntimeException('Není XML: ' . substr($xml, 0, 80));
}

Související