DEV Community

Trexmi
Trexmi

Posted on Originally published at trexmi.com

Why your XML is not well-formed: 5 errors and how to read the parser message

A parser message like Extra content at the end of the document tells you exactly what is wrong, once you know how it words things. Below are five errors that account for most broken XML I see, the message a parser prints for each, and the fix. The messages come from libxml2 (the parser behind PHP's DOMDocument, xmllint and many other tools); other parsers word them differently but point at the same problems.

1. Mismatched closing tag

<item><name>A</item>
Enter fullscreen mode Exit fullscreen mode

libxml2 says: Opening and ending tag mismatch: name line 1 and item.

The parser found </item> while <name> was still open. Close the innermost element first:

<item><name>A</name></item>
Enter fullscreen mode Exit fullscreen mode

2. An unescaped ampersand

<name>R&D</name>
Enter fullscreen mode Exit fullscreen mode

libxml2 says: EntityRef: expecting ';'.

In XML, & starts an entity reference such as &amp;. A bare ampersand in text is an error, which is why URLs with query strings break feeds. Escape it:

<name>R&amp;D</name>
Enter fullscreen mode Exit fullscreen mode

3. Two root elements

<a/><b/>
Enter fullscreen mode Exit fullscreen mode

libxml2 says: Extra content at the end of the document.

A document has exactly one root element. Wrap the siblings:

<root><a/><b/></root>
Enter fullscreen mode Exit fullscreen mode

4. A missing closing quote in an attribute

<item id="42></item>
Enter fullscreen mode Exit fullscreen mode

libxml2 says: Unescaped '<' not allowed in attributes values.

The message is confusing: the parser kept reading the attribute value past 42> until it hit the next <. The real mistake is the missing quote:

<item id="42"></item>
Enter fullscreen mode Exit fullscreen mode

Rule of thumb: when the message points at an attribute, check the quote before it.

5. ]]> inside a CDATA section

<s><![CDATA[a ]]> b]]></s>
Enter fullscreen mode Exit fullscreen mode

libxml2 says: Sequence ']]>' not allowed in content.

The sequence ]]> ends a CDATA section, so it cannot appear inside one. Split it across two sections:

<s><![CDATA[a ]]]]><![CDATA[> b]]></s>
Enter fullscreen mode Exit fullscreen mode

The text content of that element is still a ]]> b.

A note on namespaces

<media:title>Demo</media:title>
Enter fullscreen mode Exit fullscreen mode

xmllint prints namespace error : Namespace prefix media on title is not defined, yet some libraries, including PHP's DOMDocument::loadXML, still load the document and only record the problem. If a feed works in one tool and fails in another, an undeclared prefix is a likely reason. Declare it on the root: <root xmlns:media="urn:media">.

Fix fast

Fix the first error only, then re-run: one early mistake (a missing quote, an unclosed tag) often produces several later messages. To paste a document and see the line and column, I use an XML validator, then an XML formatter to indent the result. The longer reference, with namespaces, CDATA and XPath, is in the XML guide.

Top comments (0)