Add XMLNamespaces to XMLElement - Technical Analysis
Core Problem
PostgreSQL's xmlelement() function, which constructs XML elements per the SQL/XML standard, lacks support for the XMLNAMESPACES clause. This means users cannot declaratively attach XML namespace declarations to elements produced by xmlelement(). While PostgreSQL already supports XMLNAMESPACES in the context of XMLTABLE (for XPath evaluation), it does not support it in the element-construction context, which is a significant gap relative to the SQL/XML:2023 standard (Section 11.2, "XML lexically scoped options").
Without this feature, users who need namespace-qualified XML output must resort to workarounds like string manipulation or post-processing, which defeats the purpose of having structured XML construction functions.
Architectural Context
How XMLElement Currently Works
xmlelement() is implemented as a special expression node (XmlExpr) with op = IS_XMLELEMENT. The expression carries:
name: the element tag namenamed_args/arg_names: forXMLATTRIBUTES(attribute values and their names)args: content/children of the element
At execution time in xml.c, the element is constructed using libxml2's xmlTextWriter API. Attributes are written via xmlTextWriterWriteAttribute.
What the Patch Changes
The patch extends XmlExpr to carry namespace declarations alongside attributes. The implementation reuses the existing named_args/arg_names infrastructure pattern but adds a distinct mechanism for namespace declarations. Key changes span:
-
Grammar (
gram.y): Extends thexmlelementproduction rules to acceptXMLNAMESPACES(...)as an optional clause. Pavel Stehule suggested consolidating the grammar to avoid multiplicative explosion of rules by treating xmlattributes and xml_namespaces as a list of "xml_element_options." -
Parse Analysis (
parse_expr.c/transformXmlExpr): Validates namespace declarations per SQL/XML rules:- At most one DEFAULT namespace declaration
- No prefix may be
xmlorxmlns - No URI may be
http://www.w3.org/2000/xmlns/orhttp://www.w3.org/XML/1998/namespace - Non-default namespace URIs cannot be zero-length strings
-
Execution (
xml.c): UsesxmlTextWriterWriteAttributeNS(instead of plainxmlTextWriterWriteAttribute) to properly register namespace declarations with libxml2, giving the library awareness of namespace semantics. -
Rule/View Deparse (
ruleutils.c): Fixed a bug where namespace declarations in views were being incorrectly serialized asXMLATTRIBUTESinstead ofXMLNAMESPACES. -
XMLTABLE interaction: The shared
xml_namespace_listgrammar rule meansNO DEFAULTalso becomes available inXMLTABLE'sXMLNAMESPACESclause. The patch handles this by translatingNO DEFAULTto an empty string URI intransformRangeTableFunc.
Key Design Decisions and Tradeoffs
1. Expressions vs. String Constants for Namespace URIs
A significant design discussion centered on whether namespace URIs should be restricted to string constants (as DB2 and Oracle do) or allow arbitrary expressions including column references.
Arguments for expressions (adopted approach):
- PostgreSQL's general design philosophy doesn't force string constants in function arguments
- Consistency with how
XMLATTRIBUTESalready works (allows column references) - Pavel Stehule argued that PostgreSQL traditionally avoids being unnecessarily restrictive
Arguments for constants only (raised by Umar Hayat):
- Namespaces are structural/schema, not data
- Runtime validation failures mid-transaction on bad data
- Performance implications of per-row validation
- Other databases restrict this
The patch authors decided to allow expressions, accepting that runtime errors (e.g., zero-length URI for a prefixed namespace) are the user's responsibility to prevent via WHERE clauses.
2. NO DEFAULT Semantics
NO DEFAULT produces xmlns="", which in XML semantics undeclares a previously inherited default namespace. Umar Hayat initially suggested it should produce no output at all (like DEFAULT NULL), but Jim Jones correctly identified that per the XML specification, xmlns="" is the proper way to "undeclare" a default namespace in a child element scope. DB2 behaves similarly.
3. Libxml2 Namespace Management (v3 and beyond)
Starting in v3, the implementation switched from xmlTextWriterWriteAttribute (treating namespaces as plain attributes) to xmlTextWriterWriteAttributeNS, which properly informs libxml2 about namespace semantics. Jim noted that libxml2 is lenient (allowing duplicate default namespaces, allowing NO DEFAULT without prior DEFAULT), and the patch preserves user-declared namespaces even if redundant, respecting user intent.
4. Grammar Consolidation
Pavel's suggestion to avoid multiplying XMLELEMENT grammar rules by treating XMLNAMESPACES and XMLATTRIBUTES as options in a list was adopted in v3, producing cleaner grammar.
Current Status
The patch was marked "Ready for Committer" by Pavel Stehule after v3 (January 2025), then reverted to "Needs Review" by Umar Hayat who raised the XMLTABLE/NO DEFAULT interaction bug (fixed in v5). Since then, the patch has been repeatedly rebased (v6 through v11+) over 18 months without being committed, suggesting it awaits committer attention. No committer has engaged with the thread.
Outstanding Concerns
- No committer has reviewed or commented on the patch
- The patch has been in the commitfest cycle since at least CF 2025-01, surviving multiple rounds without being picked up
- Long rebase history suggests potential bitrot risk and lack of committer sponsorship