diff options
Diffstat (limited to 'src/backend/utils/adt/xml.c')
-rw-r--r-- | src/backend/utils/adt/xml.c | 34 |
1 files changed, 26 insertions, 8 deletions
diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c index a735aa28015..bfe9447295d 100644 --- a/src/backend/utils/adt/xml.c +++ b/src/backend/utils/adt/xml.c @@ -141,9 +141,10 @@ static bool print_xml_decl(StringInfo buf, const xmlChar *version, pg_enc encoding, int standalone); static xmlDocPtr xml_parse(text *data, XmlOptionType xmloption_arg, bool preserve_whitespace, int encoding); -static text *xml_xmlnodetoxmltype(xmlNodePtr cur); +static text *xml_xmlnodetoxmltype(xmlNodePtr cur, PgXmlErrorContext *xmlerrcxt); static int xml_xpathobjtoxmlarray(xmlXPathObjectPtr xpathobj, - ArrayBuildState *astate); + ArrayBuildState *astate, + PgXmlErrorContext *xmlerrcxt); #endif /* USE_LIBXML */ static StringInfo query_to_xml_internal(const char *query, char *tablename, @@ -3599,26 +3600,41 @@ SPI_sql_row_to_xmlelement(int rownum, StringInfo result, char *tablename, * return value otherwise) */ static text * -xml_xmlnodetoxmltype(xmlNodePtr cur) +xml_xmlnodetoxmltype(xmlNodePtr cur, PgXmlErrorContext *xmlerrcxt) { xmltype *result; if (cur->type == XML_ELEMENT_NODE) { xmlBufferPtr buf; + xmlNodePtr cur_copy; buf = xmlBufferCreate(); + + /* + * The result of xmlNodeDump() won't contain namespace definitions + * from parent nodes, but xmlCopyNode() duplicates a node along with + * its required namespace definitions. + */ + cur_copy = xmlCopyNode(cur, 1); + + if (cur_copy == NULL) + xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY, + "could not copy node"); + PG_TRY(); { - xmlNodeDump(buf, NULL, cur, 0, 1); + xmlNodeDump(buf, NULL, cur_copy, 0, 1); result = xmlBuffer_to_xmltype(buf); } PG_CATCH(); { + xmlFreeNode(cur_copy); xmlBufferFree(buf); PG_RE_THROW(); } PG_END_TRY(); + xmlFreeNode(cur_copy); xmlBufferFree(buf); } else @@ -3660,7 +3676,8 @@ xml_xmlnodetoxmltype(xmlNodePtr cur) */ static int xml_xpathobjtoxmlarray(xmlXPathObjectPtr xpathobj, - ArrayBuildState *astate) + ArrayBuildState *astate, + PgXmlErrorContext *xmlerrcxt) { int result = 0; Datum datum; @@ -3679,7 +3696,8 @@ xml_xpathobjtoxmlarray(xmlXPathObjectPtr xpathobj, for (i = 0; i < result; i++) { - datum = PointerGetDatum(xml_xmlnodetoxmltype(xpathobj->nodesetval->nodeTab[i])); + datum = PointerGetDatum(xml_xmlnodetoxmltype(xpathobj->nodesetval->nodeTab[i], + xmlerrcxt)); (void) accumArrayResult(astate, datum, false, XMLOID, CurrentMemoryContext); } @@ -3881,9 +3899,9 @@ xpath_internal(text *xpath_expr_text, xmltype *data, ArrayType *namespaces, * Extract the results as requested. */ if (res_nitems != NULL) - *res_nitems = xml_xpathobjtoxmlarray(xpathobj, astate); + *res_nitems = xml_xpathobjtoxmlarray(xpathobj, astate, xmlerrcxt); else - (void) xml_xpathobjtoxmlarray(xpathobj, astate); + (void) xml_xpathobjtoxmlarray(xpathobj, astate, xmlerrcxt); } PG_CATCH(); { |