@@ -140,9 +140,10 @@ static bool print_xml_decl(StringInfo buf, const xmlChar *version,
140
140
pg_enc encoding , int standalone );
141
141
static xmlDocPtr xml_parse (text * data , XmlOptionType xmloption_arg ,
142
142
bool preserve_whitespace , int encoding );
143
- static text * xml_xmlnodetoxmltype (xmlNodePtr cur );
143
+ static text * xml_xmlnodetoxmltype (xmlNodePtr cur , PgXmlErrorContext * xmlerrcxt );
144
144
static int xml_xpathobjtoxmlarray (xmlXPathObjectPtr xpathobj ,
145
- ArrayBuildState * * astate );
145
+ ArrayBuildState * * astate ,
146
+ PgXmlErrorContext * xmlerrcxt );
146
147
#endif /* USE_LIBXML */
147
148
148
149
static StringInfo query_to_xml_internal (const char * query , char * tablename ,
@@ -3593,26 +3594,41 @@ SPI_sql_row_to_xmlelement(int rownum, StringInfo result, char *tablename,
3593
3594
* return value otherwise)
3594
3595
*/
3595
3596
static text *
3596
- xml_xmlnodetoxmltype (xmlNodePtr cur )
3597
+ xml_xmlnodetoxmltype (xmlNodePtr cur , PgXmlErrorContext * xmlerrcxt )
3597
3598
{
3598
3599
xmltype * result ;
3599
3600
3600
3601
if (cur -> type == XML_ELEMENT_NODE )
3601
3602
{
3602
3603
xmlBufferPtr buf ;
3604
+ xmlNodePtr cur_copy ;
3603
3605
3604
3606
buf = xmlBufferCreate ();
3607
+
3608
+ /*
3609
+ * The result of xmlNodeDump() won't contain namespace definitions
3610
+ * from parent nodes, but xmlCopyNode() duplicates a node along with
3611
+ * its required namespace definitions.
3612
+ */
3613
+ cur_copy = xmlCopyNode (cur , 1 );
3614
+
3615
+ if (cur_copy == NULL )
3616
+ xml_ereport (xmlerrcxt , ERROR , ERRCODE_OUT_OF_MEMORY ,
3617
+ "could not copy node" );
3618
+
3605
3619
PG_TRY ();
3606
3620
{
3607
- xmlNodeDump (buf , NULL , cur , 0 , 1 );
3621
+ xmlNodeDump (buf , NULL , cur_copy , 0 , 1 );
3608
3622
result = xmlBuffer_to_xmltype (buf );
3609
3623
}
3610
3624
PG_CATCH ();
3611
3625
{
3626
+ xmlFreeNode (cur_copy );
3612
3627
xmlBufferFree (buf );
3613
3628
PG_RE_THROW ();
3614
3629
}
3615
3630
PG_END_TRY ();
3631
+ xmlFreeNode (cur_copy );
3616
3632
xmlBufferFree (buf );
3617
3633
}
3618
3634
else
@@ -3654,7 +3670,8 @@ xml_xmlnodetoxmltype(xmlNodePtr cur)
3654
3670
*/
3655
3671
static int
3656
3672
xml_xpathobjtoxmlarray (xmlXPathObjectPtr xpathobj ,
3657
- ArrayBuildState * * astate )
3673
+ ArrayBuildState * * astate ,
3674
+ PgXmlErrorContext * xmlerrcxt )
3658
3675
{
3659
3676
int result = 0 ;
3660
3677
Datum datum ;
@@ -3676,7 +3693,8 @@ xml_xpathobjtoxmlarray(xmlXPathObjectPtr xpathobj,
3676
3693
3677
3694
for (i = 0 ; i < result ; i ++ )
3678
3695
{
3679
- datum = PointerGetDatum (xml_xmlnodetoxmltype (xpathobj -> nodesetval -> nodeTab [i ]));
3696
+ datum = PointerGetDatum (xml_xmlnodetoxmltype (xpathobj -> nodesetval -> nodeTab [i ],
3697
+ xmlerrcxt ));
3680
3698
* astate = accumArrayResult (* astate , datum ,
3681
3699
false, XMLOID ,
3682
3700
CurrentMemoryContext );
@@ -3880,9 +3898,9 @@ xpath_internal(text *xpath_expr_text, xmltype *data, ArrayType *namespaces,
3880
3898
* Extract the results as requested.
3881
3899
*/
3882
3900
if (res_nitems != NULL )
3883
- * res_nitems = xml_xpathobjtoxmlarray (xpathobj , astate );
3901
+ * res_nitems = xml_xpathobjtoxmlarray (xpathobj , astate , xmlerrcxt );
3884
3902
else
3885
- (void ) xml_xpathobjtoxmlarray (xpathobj , astate );
3903
+ (void ) xml_xpathobjtoxmlarray (xpathobj , astate , xmlerrcxt );
3886
3904
}
3887
3905
PG_CATCH ();
3888
3906
{
0 commit comments