Opening and ending tag mismatch: příčina a oprava

Uzavírací značka neodpovídá poslední otevřené značce: chybí, má překlep nebo jinou velikost písmen, značky se kříží, nebo soubor skončil dřív, než se všechny uzavřely. Parser chybu pozná až u následující uzavírací značky, proto skutečná příčina bývá o kus výš, než ukazuje číslo řádku.

Autor: Aktualizováno

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

libxml2 (PHP, xmllint, lxml) hlásí Opening and ending tag mismatch, Java The element type "…" must be terminated by the matching end-tag "</…>", Python a Firefox mismatched tag, Chrome Unexpected closing tag:

Parser Hláška Kdy
libxml2 2.13 a novější PHP (DOM, SimpleXML), xmllint, Python lxml, validátor na XML.cz Opening and ending tag mismatch: polozka line 3 and Polozka Překlep nebo jiná velikost písmen v uzavírací značce
Opening and ending tag mismatch: polozka line 3 and objednavka Chybějící uzavírací značka
Opening and ending tag mismatch: i line 2 and b Křížené značky
Premature end of data in tag objednavky line 2 Useknutý soubor
Java (Xerces) DocumentBuilder, SAXParser, JAXB, Spring, Maven The element type "polozka" must be terminated by the matching end-tag "</polozka>". Překlep nebo jiná velikost písmen v uzavírací značce, Chybějící uzavírací značka
The element type "i" must be terminated by the matching end-tag "</i>". Křížené značky
XML document structures must start and end within the same entity. Useknutý soubor
Python (expat) xml.etree.ElementTree, minidom mismatched tag: line 3, column 18 Překlep nebo jiná velikost písmen v uzavírací značce
mismatched tag: line 5, column 2 Chybějící uzavírací značka
mismatched tag: line 2, column 34 Křížené značky
no element found: line 4, column 32 Useknutý soubor
.NET XmlDocument, XDocument, XmlReader The 'polozka' start tag on line 3 position 4 does not match the end tag of 'Polozka'. Line 3, position 19. Překlep nebo jiná velikost písmen v uzavírací značce
The 'polozka' start tag on line 3 position 4 does not match the end tag of 'objednavka'. Line 5, position 3. Chybějící uzavírací značka
The 'i' start tag on line 2 position 24 does not match the end tag of 'b'. Line 2, position 35. Křížené značky
Unexpected end of file has occurred. The following elements are not closed: objednavky. Line 4, position 33. Useknutý soubor
Chrome 151+ DOMParser, zobrazení XML souboru Unexpected closing tag: Polozka != polozka Překlep nebo jiná velikost písmen v uzavírací značce
Unexpected closing tag: objednavka != polozka Chybějící uzavírací značka
Unexpected closing tag: b != i Křížené značky
Unexpected end of stream: still inside the root element Useknutý soubor
Firefox DOMParser, zobrazení XML souboru mismatched tag. Expected: </polozka>. Překlep nebo jiná velikost písmen v uzavírací značce, Chybějící uzavírací značka
mismatched tag. Expected: </i>. Křížené značky
no root element found Useknutý soubor

Hláška libxml2 obsahuje dvě jména: první je otevřený element i s řádkem, kde začal (polozka line 3), druhé uzavírací značka, na které parser skončil. Java a Firefox jmenují jen otevřený element, .NET uvádí obojí i s pozicemi.

Příčiny a opravy

Překlep nebo jiná velikost písmen v uzavírací značce

Chybně
<?xml version="1.0" encoding="UTF-8"?>
<objednavka>
  <polozka>Hrnek</Polozka>
</objednavka>
Opraveno
<?xml version="1.0" encoding="UTF-8"?>
<objednavka>
  <polozka>Hrnek</polozka>
</objednavka>

XML rozlišuje velká a malá písmena, <polozka> a </Polozka> jsou dva různé názvy. Stejně se projeví překlep (</polzka>) nebo přejmenování jen otevírací značky.

Chybějící uzavírací značka

Chybně
<?xml version="1.0" encoding="UTF-8"?>
<objednavka>
  <polozka>Hrnek
  <cena>199</cena>
</objednavka>
Opraveno
<?xml version="1.0" encoding="UTF-8"?>
<objednavka>
  <polozka>Hrnek</polozka>
  <cena>199</cena>
</objednavka>

Parser si všimne až u </objednavka>, kdy čeká nejdřív </polozka>. Hlášený řádek je proto až konec nadřazeného elementu. Hledej otevírací značku, kterou hláška jmenuje (libxml2 přidává i její řádek).

Křížené značky

Chybně
<?xml version="1.0" encoding="UTF-8"?>
<poznamka>Zboží je <b><i>skladem</b></i></poznamka>
Opraveno
<?xml version="1.0" encoding="UTF-8"?>
<poznamka>Zboží je <b><i>skladem</i></b></poznamka>

HTML prohlížeč křížené značky tiše opraví, XML parser ne. Značky se musí uzavírat v opačném pořadí, než se otevřely. Častý zdroj je text zkopírovaný z HTML do elementu popisu — takový text patří do sekce CDATA, nebo se musí escapovat.

Useknutý soubor

Chybně
<?xml version="1.0" encoding="UTF-8"?>
<objednavky>
  <objednavka cislo="2026-117"/>
  <objednavka cislo="2026-118"/>
Opraveno
<?xml version="1.0" encoding="UTF-8"?>
<objednavky>
  <objednavka cislo="2026-117"/>
  <objednavka cislo="2026-118"/>
</objednavky>

Když soubor skončí uprostřed, žádná špatná uzavírací značka v něm není. libxml2 hlásí Premature end of data in tag, Java XML document structures must start and end within the same entity, Python no element found. Příčinou bývá přerušené stahování, plný disk, zápis bez zavření souboru nebo export s limitem velikosti. Oprava není v XML, ale v tom, co soubor vytvořilo — stáhni ho znovu a porovnej velikost.

Jak chybu najít

  • Nejdřív se podívej na element, který hláška jmenuje jako otevřený, ne na řádek, kde parser skončil.
  • V editoru s podporou XML (VS Code, Notepad++) sbal elementy od kořene dolů. Element, který nejde sbalit tam, kde čekáš, je ten neuzavřený.
  • Validátor na XML.cz u neuzavřeného elementu zvýrazní i jeho otevírací značku, takže vidíš oba konce problému najednou.
  • U velkých souborů pomůže porovnat soubor s poslední verzí, která fungovala, a podívat se jen na změněná místa.

Prevence v kódu

Neuzavřené a překlepnuté značky skoro vždy vznikají skládáním XML z řetězců. Knihovna, která dokument sestaví ze stromu, značky uzavře sama:

Python
import xml.etree.ElementTree as ET

objednavka = ET.Element("objednavka")
ET.SubElement(objednavka, "polozka").text = "Hrnek"
ET.SubElement(objednavka, "cena").text = "199"
ET.ElementTree(objednavka).write("objednavka.xml", encoding="UTF-8", xml_declaration=True)

Obdobně poslouží DOMDocument v PHP, XDocument v .NET nebo XMLStreamWriter v Javě. Postupy pro jednotlivé jazyky jsou v kapitolách XML v PHP, XML v C# a XML v JavaScriptu.

Související