X Xerobit

XML Validator Online — Check XML Syntax and Structure

An XML validator checks that XML is well-formed (correct syntax) and optionally valid against a schema (DTD or XSD). Here's what makes XML invalid and how to fix common...

Mian Ali Khalid · · 5 min read
Use the tool
XML Formatter
Format, validate, and beautify XML documents.
Open XML Formatter →

XML validation has two levels: well-formedness (syntax rules every XML document must follow) and validity (conformance to a specific schema like DTD or XSD). A validator checks both. Invalid XML won’t parse; ill-formed XML silently fails or throws cryptic errors.

Use the XML Formatter to validate, format, and inspect XML documents.

Well-formed XML rules

Every XML document must follow these rules regardless of schema:

1. One root element

<!-- INVALID: multiple root elements -->
<user>Alice</user>
<user>Bob</user>

<!-- VALID: single root element -->
<users>
  <user>Alice</user>
  <user>Bob</user>
</users>

2. All elements must be properly closed

<!-- INVALID: unclosed element -->
<name>Alice

<!-- INVALID: self-closing wrong syntax -->
<name/>content</name>

<!-- VALID: closed element -->
<name>Alice</name>

<!-- VALID: self-closing empty element -->
<name/>

3. Tags must be properly nested

<!-- INVALID: overlapping tags -->
<b><i>bold italic</b></i>

<!-- VALID: properly nested -->
<b><i>bold italic</i></b>

4. Attribute values must be quoted

<!-- INVALID: unquoted attribute -->
<user id=123>Alice</user>

<!-- VALID: quoted attribute -->
<user id="123">Alice</user>

5. Attribute names must be unique in an element

<!-- INVALID: duplicate attribute -->
<user id="1" id="2">Alice</user>

<!-- VALID: unique attributes -->
<user id="1" role="admin">Alice</user>

6. Special characters must be escaped

<!-- INVALID: raw < and & in content -->
<description>5 < 10 & temperature rises</description>

<!-- VALID: escaped entities -->
<description>5 &lt; 10 &amp; temperature rises</description>

<!-- VALID: CDATA section for complex content -->
<description><![CDATA[5 < 10 & "quotes" work here]]></description>

XML escape sequences:

CharacterEscape
<&lt;
>&gt;
&&amp;
"&quot;
'&apos;

Common validation errors and fixes

Error: “Content is not allowed in prolog”

Error: Content is not allowed in prolog.

Usually caused by a BOM (Byte Order Mark) or whitespace before the XML declaration:

<!-- WRONG: space before declaration -->
 <?xml version="1.0"?>

<!-- CORRECT: declaration must be first character -->
<?xml version="1.0"?>
<root/>

Error: “The reference to entity X must end with ’;’”

Error: The reference to entity "brand" must end with ';'.

You used &brand instead of &amp; or a defined entity:

<!-- WRONG -->
<name>Johnson & Johnson</name>

<!-- CORRECT -->
<name>Johnson &amp; Johnson</name>

Error: “Attribute name X associated with an element type Y must be followed by the ’=’ character”

Error: Attribute name "class" associated with an element type "div"
must be followed by the '=' character.

Missing = in attribute, or using HTML void elements (like <br>) in an XML context:

<!-- WRONG (HTML-style): -->
<br>
<input type="text">

<!-- CORRECT (XML/XHTML): -->
<br/>
<input type="text"/>

Error: “The element X must be terminated by the matching end-tag”

Mismatched or missing closing tags:

<!-- WRONG: wrong closing tag -->
<Title>My Document</title>

<!-- XML is case-sensitive! -->
<!-- CORRECT: -->
<Title>My Document</Title>

Validating against XML Schema (XSD)

XSD (XML Schema Definition) defines the structure, data types, and constraints your XML must follow.

Example XSD schema:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="users">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="user" maxOccurs="unbounded">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="name" type="xs:string"/>
              <xs:element name="email" type="xs:string"/>
              <xs:element name="age" type="xs:positiveInteger" minOccurs="0"/>
            </xs:sequence>
            <xs:attribute name="id" type="xs:integer" use="required"/>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

Valid XML document against this schema:

<?xml version="1.0" encoding="UTF-8"?>
<users>
  <user id="1">
    <name>Alice</name>
    <email>alice@example.com</email>
    <age>30</age>
  </user>
  <user id="2">
    <name>Bob</name>
    <email>bob@example.com</email>
  </user>
</users>

Invalid document (missing required id attribute):

<user>  <!-- Missing id attribute → validation error -->
  <name>Alice</name>
  <email>alice@example.com</email>
</user>

Validating XML in code

JavaScript (browser — DOMParser)

function validateXML(xmlString) {
  const parser = new DOMParser();
  const doc = parser.parseFromString(xmlString, 'application/xml');
  const error = doc.querySelector('parsererror');
  
  if (error) {
    return { valid: false, error: error.textContent };
  }
  return { valid: true };
}

const result = validateXML('<root><item>test</item></root>');
console.log(result);  // { valid: true }

const badResult = validateXML('<root><item>test</root>');
console.log(badResult);  // { valid: false, error: "..." }

Node.js (fast-xml-parser)

const { XMLParser, XMLValidator } = require('fast-xml-parser');

const xmlString = `<users>
  <user id="1">
    <name>Alice</name>
  </user>
</users>`;

// Check well-formedness:
const result = XMLValidator.validate(xmlString);
if (result === true) {
  console.log('Valid XML');
} else {
  console.log('Invalid:', result.err.msg, 'at line', result.err.line);
}

// Parse (throws on invalid):
const parser = new XMLParser({ ignoreAttributes: false });
try {
  const json = parser.parse(xmlString);
  console.log(json);
} catch (e) {
  console.error('Parse error:', e.message);
}

Python (lxml)

from lxml import etree

def validate_xml(xml_string, xsd_string=None):
    try:
        doc = etree.fromstring(xml_string.encode())
        
        if xsd_string:
            schema_doc = etree.fromstring(xsd_string.encode())
            schema = etree.XMLSchema(schema_doc)
            if not schema.validate(doc):
                return False, str(schema.error_log)
        
        return True, None
    except etree.XMLSyntaxError as e:
        return False, str(e)

# Check well-formedness:
valid, error = validate_xml('<root><item>test</item></root>')
print(valid)  # True

# Check against XSD:
xsd = '<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">...</xs:schema>'
valid, error = validate_xml(xml_doc, xsd)

DTD validation

DTD (Document Type Definition) is the older schema format, still used in legacy systems:

<?xml version="1.0"?>
<!DOCTYPE users [
  <!ELEMENT users (user+)>
  <!ELEMENT user (name, email)>
  <!ELEMENT name (#PCDATA)>
  <!ELEMENT email (#PCDATA)>
  <!ATTLIST user id ID #REQUIRED>
]>
<users>
  <user id="u1">
    <name>Alice</name>
    <email>alice@example.com</email>
  </user>
</users>

DTD has significant limitations compared to XSD: no data type support, weaker namespace handling, and no ability to constrain numeric ranges. Use XSD for new schemas.


Related posts

Related tool

XML Formatter

Format, validate, and beautify XML documents.

Written by Mian Ali Khalid. Part of the Data & Format pillar.