@@ -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 ,
@@ -3606,26 +3607,41 @@ SPI_sql_row_to_xmlelement(int rownum, StringInfo result, char *tablename,
3606
3607
* return value otherwise)
3607
3608
*/
3608
3609
static text *
3609
- xml_xmlnodetoxmltype (xmlNodePtr cur )
3610
+ xml_xmlnodetoxmltype (xmlNodePtr cur , PgXmlErrorContext * xmlerrcxt )
3610
3611
{
3611
3612
xmltype * result ;
3612
3613
3613
3614
if (cur -> type == XML_ELEMENT_NODE )
3614
3615
{
3615
3616
xmlBufferPtr buf ;
3617
+ xmlNodePtr cur_copy ;
3616
3618
3617
3619
buf = xmlBufferCreate ();
3620
+
3621
+ /*
3622
+ * The result of xmlNodeDump() won't contain namespace definitions
3623
+ * from parent nodes, but xmlCopyNode() duplicates a node along with
3624
+ * its required namespace definitions.
3625
+ */
3626
+ cur_copy = xmlCopyNode (cur , 1 );
3627
+
3628
+ if (cur_copy == NULL )
3629
+ xml_ereport (xmlerrcxt , ERROR , ERRCODE_OUT_OF_MEMORY ,
3630
+ "could not copy node" );
3631
+
3618
3632
PG_TRY ();
3619
3633
{
3620
- xmlNodeDump (buf , NULL , cur , 0 , 1 );
3634
+ xmlNodeDump (buf , NULL , cur_copy , 0 , 1 );
3621
3635
result = xmlBuffer_to_xmltype (buf );
3622
3636
}
3623
3637
PG_CATCH ();
3624
3638
{
3639
+ xmlFreeNode (cur_copy );
3625
3640
xmlBufferFree (buf );
3626
3641
PG_RE_THROW ();
3627
3642
}
3628
3643
PG_END_TRY ();
3644
+ xmlFreeNode (cur_copy );
3629
3645
xmlBufferFree (buf );
3630
3646
}
3631
3647
else
@@ -3667,7 +3683,8 @@ xml_xmlnodetoxmltype(xmlNodePtr cur)
3667
3683
*/
3668
3684
static int
3669
3685
xml_xpathobjtoxmlarray (xmlXPathObjectPtr xpathobj ,
3670
- ArrayBuildState * * astate )
3686
+ ArrayBuildState * * astate ,
3687
+ PgXmlErrorContext * xmlerrcxt )
3671
3688
{
3672
3689
int result = 0 ;
3673
3690
Datum datum ;
@@ -3689,7 +3706,8 @@ xml_xpathobjtoxmlarray(xmlXPathObjectPtr xpathobj,
3689
3706
3690
3707
for (i = 0 ; i < result ; i ++ )
3691
3708
{
3692
- datum = PointerGetDatum (xml_xmlnodetoxmltype (xpathobj -> nodesetval -> nodeTab [i ]));
3709
+ datum = PointerGetDatum (xml_xmlnodetoxmltype (xpathobj -> nodesetval -> nodeTab [i ],
3710
+ xmlerrcxt ));
3693
3711
* astate = accumArrayResult (* astate , datum ,
3694
3712
false, XMLOID ,
3695
3713
CurrentMemoryContext );
@@ -3893,9 +3911,9 @@ xpath_internal(text *xpath_expr_text, xmltype *data, ArrayType *namespaces,
3893
3911
* Extract the results as requested.
3894
3912
*/
3895
3913
if (res_nitems != NULL )
3896
- * res_nitems = xml_xpathobjtoxmlarray (xpathobj , astate );
3914
+ * res_nitems = xml_xpathobjtoxmlarray (xpathobj , astate , xmlerrcxt );
3897
3915
else
3898
- (void ) xml_xpathobjtoxmlarray (xpathobj , astate );
3916
+ (void ) xml_xpathobjtoxmlarray (xpathobj , astate , xmlerrcxt );
3899
3917
}
3900
3918
PG_CATCH ();
3901
3919
{
0 commit comments