77 * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
88 * Portions Copyright (c) 1994, Regents of the University of California
99 *
10- * $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.10 2007/01/05 22: 19:42 momjian Exp $
10+ * $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.11 2007/01/06 19:18:36 petere Exp $
1111 *
1212 *-------------------------------------------------------------------------
1313 */
3131#include <libxml/tree.h>
3232#include <libxml/uri.h>
3333#include <libxml/xmlerror.h>
34+ #include <libxml/xmlsave.h>
3435#endif /* USE_LIBXML */
3536
3637#include "fmgr.h"
4950static StringInfo xml_err_buf = NULL ;
5051
5152static void xml_init (void );
53+ #ifdef NOT_USED
5254static void * xml_palloc (size_t size );
5355static void * xml_repalloc (void * ptr ,size_t size );
5456static void xml_pfree (void * ptr );
5557static char * xml_pstrdup (const char * string );
58+ #endif
5659static void xml_ereport (int level ,int sqlcode ,
5760const char * msg ,void * ctxt );
5861static void xml_errorHandler (void * ctxt ,const char * msg , ...);
@@ -76,6 +79,7 @@ xml_in(PG_FUNCTION_ARGS)
7679char * s = PG_GETARG_CSTRING (0 );
7780size_t len ;
7881xmltype * vardata ;
82+ xmlDocPtr doc ;
7983
8084len = strlen (s );
8185vardata = palloc (len + VARHDRSZ );
@@ -86,7 +90,8 @@ xml_in(PG_FUNCTION_ARGS)
8690 * Parse the data to check if it is well-formed XML data. Assume
8791 * that ERROR occurred if parsing failed.
8892 */
89- xml_parse (vardata , false, true);
93+ doc = xml_parse (vardata , false, true);
94+ xmlFreeDoc (doc );
9095
9196PG_RETURN_XML_P (vardata );
9297#else
@@ -120,6 +125,7 @@ xml_recv(PG_FUNCTION_ARGS)
120125xmltype * result ;
121126char * str ;
122127int nbytes ;
128+ xmlDocPtr doc ;
123129
124130str = pq_getmsgtext (buf ,buf -> len - buf -> cursor ,& nbytes );
125131
@@ -132,7 +138,8 @@ xml_recv(PG_FUNCTION_ARGS)
132138 * Parse the data to check if it is well-formed XML data. Assume
133139 * that ERROR occurred if parsing failed.
134140 */
135- xml_parse (result , false, true);
141+ doc = xml_parse (result , false, true);
142+ xmlFreeDoc (doc );
136143
137144PG_RETURN_XML_P (result );
138145#else
@@ -175,6 +182,21 @@ stringinfo_to_xmltype(StringInfo buf)
175182
176183return result ;
177184}
185+
186+
187+ static xmltype *
188+ xmlBuffer_to_xmltype (xmlBufferPtr buf )
189+ {
190+ int32 len ;
191+ xmltype * result ;
192+
193+ len = xmlBufferLength (buf )+ VARHDRSZ ;
194+ result = palloc (len );
195+ VARATT_SIZEP (result )= len ;
196+ memcpy (VARDATA (result ),xmlBufferContent (buf ),len - VARHDRSZ );
197+
198+ return result ;
199+ }
178200#endif
179201
180202
@@ -221,7 +243,10 @@ xmltype *
221243xmlparse (text * data ,bool is_document ,bool preserve_whitespace )
222244{
223245#ifdef USE_LIBXML
224- xml_parse (data ,is_document ,preserve_whitespace );
246+ xmlDocPtr doc ;
247+
248+ doc = xml_parse (data ,is_document ,preserve_whitespace );
249+ xmlFreeDoc (doc );
225250
226251return (xmltype * )data ;
227252#else
@@ -280,31 +305,38 @@ xmltype *
280305xmlroot (xmltype * data ,text * version ,int standalone )
281306{
282307#ifdef USE_LIBXML
283- xmltype * result ;
284- StringInfoData buf ;
308+ xmlDocPtr doc ;
309+ xmlBufferPtr buffer ;
310+ xmlSaveCtxtPtr save ;
285311
286- initStringInfo ( & buf );
312+ doc = xml_parse (( text * ) data , true, true );
287313
288- /*
289- * FIXME: This is probably supposed to be cleverer if there
290- * already is an XML preamble.
291- */
292- appendStringInfo (& buf ,"<?xml" );
293314if (version )
315+ doc -> version = xmlStrdup (xml_text2xmlChar (version ));
316+ else
317+ doc -> version = NULL ;
318+
319+ switch (standalone )
294320{
295- appendStringInfo (& buf ," version=\"" );
296- appendStringInfoText (& buf ,version );
297- appendStringInfo (& buf ,"\"" );
321+ case 1 :
322+ doc -> standalone = 1 ;
323+ break ;
324+ case -1 :
325+ doc -> standalone = 0 ;
326+ break ;
327+ default :
328+ doc -> standalone = -1 ;
329+ break ;
298330}
299- if (standalone )
300- appendStringInfo (& buf ," standalone=\"%s\"" ,
301- (standalone == 1 ?"yes" :"no" ));
302- appendStringInfo (& buf ,"?>" );
303- appendStringInfoText (& buf , (text * )data );
304331
305- result = stringinfo_to_xmltype (& buf );
306- pfree (buf .data );
307- return result ;
332+ buffer = xmlBufferCreate ();
333+ save = xmlSaveToBuffer (buffer ,NULL ,0 );
334+ xmlSaveDoc (save ,doc );
335+ xmlSaveClose (save );
336+
337+ xmlFreeDoc (doc );
338+
339+ return xmlBuffer_to_xmltype (buffer );
308340#else
309341NO_XML_SUPPORT ();
310342return NULL ;
@@ -444,7 +476,14 @@ xml_init(void)
444476/* Now that xml_err_buf exists, safe to call xml_errorHandler */
445477xmlSetGenericErrorFunc (NULL ,xml_errorHandler );
446478
479+ #ifdef NOT_USED
480+ /*
481+ * FIXME: This doesn't work because libxml assumes that whatever
482+ * libxml allocates, only libxml will free, so we can't just drop
483+ * memory contexts behind it. This needs to be refined.
484+ */
447485xmlMemSetup (xml_pfree ,xml_palloc ,xml_repalloc ,xml_pstrdup );
486+ #endif
448487xmlInitParser ();
449488LIBXML_TEST_VERSION ;
450489}
@@ -528,8 +567,6 @@ xml_parse(text *data, bool is_document, bool preserve_whitespace)
528567 * ) */
529568/* ... */
530569
531- if (doc )
532- xmlFreeDoc (doc );
533570if (ctxt )
534571xmlFreeParserCtxt (ctxt );
535572xmlCleanupParser ();
@@ -538,6 +575,7 @@ xml_parse(text *data, bool is_document, bool preserve_whitespace)
538575{
539576if (doc )
540577xmlFreeDoc (doc );
578+ doc = NULL ;
541579if (ctxt )
542580xmlFreeParserCtxt (ctxt );
543581xmlCleanupParser ();
@@ -567,6 +605,7 @@ xml_text2xmlChar(text *in)
567605}
568606
569607
608+ #ifdef NOT_USED
570609/*
571610 * Wrappers for memory management functions
572611 */
@@ -596,6 +635,7 @@ xml_pstrdup(const char *string)
596635{
597636return pstrdup (string );
598637}
638+ #endif /* NOT_USED */
599639
600640
601641/*