XMLElement() and XMLForest() embed the XML declaration of xml arguments

From: Jim Jones <jim(dot)jones(at)uni-muenster(dot)de>
To: PostgreSQL Hackers <pgsql-hackers(at)postgresql(dot)org>
Subject: XMLElement() and XMLForest() embed the XML declaration of xml arguments
Date: 2026-11-10 12:29:20
Message-ID: b13f297c-09da-4300-a3b1-6a3fa34accb5@uni-muenster.de
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi

When an xml value with an XML declaration is used as element content,
xmlelement() and xmlforest() copy the declaration into the element, for
example:

== master ==

postgres=# select xmlelement(name e, '<?xml version="1.0"
standalone="yes"?><a/>'::xml);
xmlelement
---------------------------------------------------
<e><?xml version="1.0" standalone="yes"?><a/></e>
(1 row)

A declaration is only allowed at the start of a document, so xml_in()
rejects the result,and it cannot be restored from a dump..

postgres=# select xmlelement(name e, '<?xml version="1.0"
standalone="yes"?><a/>'::xml)::text::xml;
ERROR: invalid XML content
DETAIL: line 1: XML declaration allowed only at the start of the document
<e><?xml version="1.0" standalone="yes"?><a/></e>
^

For reference, xmlconcat() drops the declarations of its arguments...

postgres=# select xmlconcat('<e/>'::xml, '<?xml version="1.0"
standalone="yes"?><a/>'::xml);
xmlconcat
-----------
<e/><a/>
(1 row)

IIUC, the SQL/XML (ISO/IEC 9075-14) says that XMLELEMENT (6.15) and
XMLFOREST (6.16) take an xml argument as is and pass it to "Removing
XQuery document nodes from an XQuery sequence" (10.19), which does what
its name says: "Replace each XQuery document node in a sequence by the
sequence of children of the XQuery document node." Only the children of
the document end up in the element, and the declaration is not one of them.

The attached patch adds a flag to xml_out_internal() to omit the
declaration, and uses it in map_sql_value_to_xml_value() when an xml
value is embedded as content. Attribute values are not affected.

== patched ==

postgres=# select xmlelement(name e, '<?xml version="1.0"
standalone="yes"?><a/>'::xml);
xmlelement
-------------
<e><a/></e>
(1 row)

BTW Oracle[1] and Db2[2] both drop the declaration as well.

Thoughts on this approach?

Best, Jim

1 - https://dbfiddle.uk/gyzP8Wet
2 - https://dbfiddle.uk/NL09RP-8

Attachment Content-Type Size
v1-0001-Omit-the-XML-declaration-of-xml-values-embedded-a.patch text/x-patch 5.0 KB

Browse pgsql-hackers by date

  From Date Subject
Next Message Koshi Shibagaki (Fujitsu) 2026-11-10 12:49:42 Re: [PATCH] reindexdb: Fix schema name lookup in parallel mode
Previous Message Tomas Vondra 2026-11-10 12:20:08 Re: improving handling of FPIs during recovery prefetching