PostgreSQL Error 2200N: invalid xml content
PostgreSQL error code 2200N: invalid xml content occurs when the database attempts to parse or store a string as XML but finds that the content does not conform to valid XML syntax rules. This error is raised when inserting data into an xml type column or using XML functions such as XMLPARSE(), XMLELEMENT(), or XMLROOT(). PostgreSQL enforces strict ISO SQL XML standards, meaning even a minor syntax violation will immediately trigger this error.
Top 3 Causes
1. Missing or Multiple Root Elements
A valid XML document must have exactly one root element. Passing an XML fragment with no root or with multiple top-level elements will cause this error.
-- ❌ Fails: multiple root elements (no single root)
SELECT XMLPARSE(DOCUMENT '<item>A</item><item>B</item>');
-- ERROR: invalid xml content
-- ✅ Fix: wrap in a single root element
SELECT XMLPARSE(DOCUMENT '<items><item>A</item><item>B</item></items>');
-- ✅ Correct INSERT into an xml-typed column
CREATE TABLE orders (id SERIAL PRIMARY KEY, data XML);
INSERT INTO orders (data)
VALUES (XMLPARSE(DOCUMENT '<?xml version="1.0" encoding="UTF-8"?>
<order>
<product>Laptop</product>
<qty>1</qty>
</order>'));
2. Unescaped Special Characters
Characters such as &, <, >, ", and ' have special meaning in XML and must be escaped as &, <, >, ", and ' respectively. Inserting raw special characters breaks the XML parser immediately.
-- ❌ Fails: unescaped ampersand and less-than sign
SELECT XMLPARSE(DOCUMENT '<note>Price < 100 & tax included</note>');
-- ERROR: invalid xml content
-- ✅ Fix: properly escape special characters
SELECT XMLPARSE(DOCUMENT '<note>Price < 100 & tax included</note>');
-- ✅ Use XMLELEMENT to escape automatically
SELECT XMLELEMENT(
NAME "note",
'Price < 100 & tax included'
);
-- Output: <note>Price < 100 & tax included</note>
3. Unclosed or Improperly Nested Tags
Unlike HTML, XML requires every tag to be explicitly closed and correctly nested. Cross-nested tags or self-closing HTML-style tags without proper XML syntax will fail validation.
-- ❌ Fails: cross-nested tags
SELECT XMLPARSE(DOCUMENT '<a><b></a></b>');
-- ERROR: invalid xml content
-- ❌ Fails: unclosed tag
SELECT XMLPARSE(DOCUMENT '<root><br><child>text</child></root>');
-- ✅ Fix: correct nesting and explicit closing tags
SELECT XMLPARSE(DOCUMENT '
<root>
<section>
<br/>
<child>text</child>
</section>
</root>');
Quick Fix Solutions
Use the helper function below to identify invalid XML records before they cause runtime errors:
-- Create a validation helper function
CREATE OR REPLACE FUNCTION is_valid_xml(p_text TEXT)
RETURNS BOOLEAN AS $$
BEGIN
PERFORM XMLPARSE(DOCUMENT p_text);
RETURN TRUE;
EXCEPTION
WHEN invalid_xml_content THEN RETURN FALSE;
WHEN others THEN RETURN FALSE;
END;
$$ LANGUAGE plpgsql;
-- Find all invalid XML rows in a staging table
SELECT id, raw_data
FROM staging_table
WHERE NOT is_valid_xml(raw_data);
-- Safely cast only valid rows into the production table
INSERT INTO production_table (data)
SELECT XMLPARSE(DOCUMENT raw_data)
FROM staging_table
WHERE is_valid_xml(raw_data);
Prevention Tips
1. Use native xml type columns. PostgreSQL automatically validates XML on every INSERT and UPDATE when the column type is xml, preventing invalid data from ever entering the database.
-- Prefer native xml type over text
CREATE TABLE documents (
id SERIAL PRIMARY KEY,
content XML -- auto-validated on every write
);
2. Always use XML libraries, never raw string concatenation. Build XML programmatically using dedicated libraries (lxml in Python, JAXB in Java, xmlbuilder2 in Node.js) to guarantee correct escaping and structure. Validate the output before sending it to PostgreSQL.
Related Errors
-
2200M: invalid XML document— Similar to2200Nbut focused on document-level structural issues such as malformed XML declarations. -
22021: character not in repertoire— Triggered when XML contains characters unsupported by the current database encoding; often appears alongside2200Nin encoding mismatch scenarios. -
42804: datatype mismatch— Occurs when incompatible types are provided to XML-expecting columns or functions.
📖 Want a more detailed guide?
Check out the full in-depth version (Korean) on oraerror.com — includes detailed analysis, additional SQL examples, and prevention tips.
Top comments (0)