@@ -141,9 +141,10 @@ static bool print_xml_decl(StringInfo buf, const xmlChar *version,
141
141
pg_enc encoding , int standalone );
142
142
static xmlDocPtr xml_parse (text * data , XmlOptionType xmloption_arg ,
143
143
bool preserve_whitespace , int encoding );
144
- static text * xml_xmlnodetoxmltype (xmlNodePtr cur );
144
+ static text * xml_xmlnodetoxmltype (xmlNodePtr cur , PgXmlErrorContext * xmlerrcxt );
145
145
static int xml_xpathobjtoxmlarray (xmlXPathObjectPtr xpathobj ,
146
- ArrayBuildState * astate );
146
+ ArrayBuildState * astate ,
147
+ PgXmlErrorContext * xmlerrcxt );
147
148
#endif /* USE_LIBXML */
148
149
149
150
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,
3599
3600
* return value otherwise)
3600
3601
*/
3601
3602
static text *
3602
- xml_xmlnodetoxmltype (xmlNodePtr cur )
3603
+ xml_xmlnodetoxmltype (xmlNodePtr cur , PgXmlErrorContext * xmlerrcxt )
3603
3604
{
3604
3605
xmltype * result ;
3605
3606
3606
3607
if (cur -> type == XML_ELEMENT_NODE )
3607
3608
{
3608
3609
xmlBufferPtr buf ;
3610
+ xmlNodePtr cur_copy ;
3609
3611
3610
3612
buf = xmlBufferCreate ();
3613
+
3614
+ /*
3615
+ * The result of xmlNodeDump() won't contain namespace definitions
3616
+ * from parent nodes, but xmlCopyNode() duplicates a node along with
3617
+ * its required namespace definitions.
3618
+ */
3619
+ cur_copy = xmlCopyNode (cur , 1 );
3620
+
3621
+ if (cur_copy == NULL )
3622
+ xml_ereport (xmlerrcxt , ERROR , ERRCODE_OUT_OF_MEMORY ,
3623
+ "could not copy node" );
3624
+
3611
3625
PG_TRY ();
3612
3626
{
3613
- xmlNodeDump (buf , NULL , cur , 0 , 1 );
3627
+ xmlNodeDump (buf , NULL , cur_copy , 0 , 1 );
3614
3628
result = xmlBuffer_to_xmltype (buf );
3615
3629
}
3616
3630
PG_CATCH ();
3617
3631
{
3632
+ xmlFreeNode (cur_copy );
3618
3633
xmlBufferFree (buf );
3619
3634
PG_RE_THROW ();
3620
3635
}
3621
3636
PG_END_TRY ();
3637
+ xmlFreeNode (cur_copy );
3622
3638
xmlBufferFree (buf );
3623
3639
}
3624
3640
else
@@ -3660,7 +3676,8 @@ xml_xmlnodetoxmltype(xmlNodePtr cur)
3660
3676
*/
3661
3677
static int
3662
3678
xml_xpathobjtoxmlarray (xmlXPathObjectPtr xpathobj ,
3663
- ArrayBuildState * astate )
3679
+ ArrayBuildState * astate ,
3680
+ PgXmlErrorContext * xmlerrcxt )
3664
3681
{
3665
3682
int result = 0 ;
3666
3683
Datum datum ;
@@ -3679,7 +3696,8 @@ xml_xpathobjtoxmlarray(xmlXPathObjectPtr xpathobj,
3679
3696
3680
3697
for (i = 0 ; i < result ; i ++ )
3681
3698
{
3682
- datum = PointerGetDatum (xml_xmlnodetoxmltype (xpathobj -> nodesetval -> nodeTab [i ]));
3699
+ datum = PointerGetDatum (xml_xmlnodetoxmltype (xpathobj -> nodesetval -> nodeTab [i ],
3700
+ xmlerrcxt ));
3683
3701
(void ) accumArrayResult (astate , datum , false,
3684
3702
XMLOID , CurrentMemoryContext );
3685
3703
}
@@ -3881,9 +3899,9 @@ xpath_internal(text *xpath_expr_text, xmltype *data, ArrayType *namespaces,
3881
3899
* Extract the results as requested.
3882
3900
*/
3883
3901
if (res_nitems != NULL )
3884
- * res_nitems = xml_xpathobjtoxmlarray (xpathobj , astate );
3902
+ * res_nitems = xml_xpathobjtoxmlarray (xpathobj , astate , xmlerrcxt );
3885
3903
else
3886
- (void ) xml_xpathobjtoxmlarray (xpathobj , astate );
3904
+ (void ) xml_xpathobjtoxmlarray (xpathobj , astate , xmlerrcxt );
3887
3905
}
3888
3906
PG_CATCH ();
3889
3907
{
0 commit comments