Use libxml's xmlwriter API for producing XML elements, instead of doing
authorPeter Eisentraut <peter_e@gmx.net>
Wed, 10 Jan 2007 20:33:54 +0000 (20:33 +0000)
committerPeter Eisentraut <peter_e@gmx.net>
Wed, 10 Jan 2007 20:33:54 +0000 (20:33 +0000)
our own printing dance.  This does a better job of quoting and escaping the
values.

src/backend/executor/execQual.c
src/backend/utils/adt/xml.c
src/include/utils/xml.h

index c23680f11be036cc8e029fc57fe90eb9a7803c3b..994f7d57ac47dbe97ecc9620e04f76eb5607186c 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.204 2007/01/07 22:49:55 petere Exp $
+ *   $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.205 2007/01/10 20:33:54 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2654,7 +2654,6 @@ ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
    char           *str;
    ListCell       *arg;
    ListCell   *narg;
-   bool    found_arg;
    int             i;
 
    if (isDone)
@@ -2682,55 +2681,6 @@ ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
            }
            break;
 
-       case IS_XMLELEMENT:
-           initStringInfo(&buf);
-           *isNull = false;
-           appendStringInfo(&buf, "<%s", xexpr->name);
-           i = 0;
-           forboth(arg, xmlExpr->named_args, narg, xexpr->arg_names)
-           {
-               ExprState   *e = (ExprState *) lfirst(arg);
-               char    *argname = strVal(lfirst(narg));
-
-               value = ExecEvalExpr(e, econtext, &isnull, NULL);
-               if (!isnull)
-               {
-                   str = OutputFunctionCall(&xmlExpr->named_outfuncs[i],
-                                            value);
-                   appendStringInfo(&buf, " %s=\"%s\"", argname, str);
-                   pfree(str);
-               }
-               i++;
-           }
-
-           found_arg = false;
-           foreach(arg, xmlExpr->args)
-           {
-               ExprState   *e = (ExprState *) lfirst(arg);
-
-               value = ExecEvalExpr(e, econtext, &isnull, NULL);
-               if (!isnull)
-               {
-                   if (!found_arg)
-                   {
-                       appendStringInfoChar(&buf, '>');
-                       found_arg = true;
-                   }
-
-                   /* we know the value is XML type */
-                   str = DatumGetCString(DirectFunctionCall1(xml_out,
-                                                             value));
-                   appendStringInfoString(&buf, str);
-                   pfree(str);
-               }
-           }
-
-           if (!found_arg)
-               appendStringInfo(&buf, "/>");
-           else
-               appendStringInfo(&buf, "</%s>", xexpr->name);
-           break;
-
        case IS_XMLFOREST:
            initStringInfo(&buf);
            i = 0;
@@ -2754,6 +2704,11 @@ ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
            break;
 
            /* The remaining cases don't need to set up buf */
+       case IS_XMLELEMENT:
+           *isNull = false;
+           return PointerGetDatum(xmlelement(xmlExpr, econtext));
+           break;
+
        case IS_XMLPARSE:
            {
                ExprState   *e;
index 5137834efb1a6e97dc7d266baf712e3a002ba5fb..5616259b29e56a18d76226ea89e1cfd34318b303 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.13 2007/01/07 22:49:56 petere Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.14 2007/01/10 20:33:54 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include <libxml/uri.h>
 #include <libxml/xmlerror.h>
 #include <libxml/xmlsave.h>
+#include <libxml/xmlwriter.h>
 #endif /* USE_LIBXML */
 
+#include "executor/executor.h"
 #include "fmgr.h"
 #include "libpq/pqformat.h"
 #include "mb/pg_wchar.h"
@@ -239,6 +241,71 @@ texttoxml(PG_FUNCTION_ARGS)
 }
 
 
+xmltype *
+xmlelement(XmlExprState *xmlExpr, ExprContext *econtext)
+{
+#ifdef USE_LIBXML
+   XmlExpr    *xexpr = (XmlExpr *) xmlExpr->xprstate.expr;
+   int         i;
+   ListCell   *arg;
+   ListCell   *narg;
+   bool        isnull;
+   xmltype    *result;
+   Datum       value;
+   char       *str;
+
+   xmlBufferPtr buf;
+   xmlTextWriterPtr writer;
+
+   buf = xmlBufferCreate();
+   writer = xmlNewTextWriterMemory(buf, 0);
+
+   xmlTextWriterStartElement(writer, (xmlChar *) xexpr->name);
+
+   i = 0;
+   forboth(arg, xmlExpr->named_args, narg, xexpr->arg_names)
+   {
+       ExprState   *e = (ExprState *) lfirst(arg);
+       char    *argname = strVal(lfirst(narg));
+
+       value = ExecEvalExpr(e, econtext, &isnull, NULL);
+       if (!isnull)
+       {
+           str = OutputFunctionCall(&xmlExpr->named_outfuncs[i], value);
+           xmlTextWriterWriteAttribute(writer, (xmlChar *) argname, (xmlChar *) str);
+           pfree(str);
+       }
+       i++;
+   }
+
+   foreach(arg, xmlExpr->args)
+   {
+       ExprState   *e = (ExprState *) lfirst(arg);
+
+       value = ExecEvalExpr(e, econtext, &isnull, NULL);
+       if (!isnull)
+       {
+           /* we know the value is XML type */
+           str = DatumGetCString(DirectFunctionCall1(xml_out,
+                                                     value));
+           xmlTextWriterWriteRaw(writer, (xmlChar *) str);
+           pfree(str);
+       }
+   }
+
+   xmlTextWriterEndElement(writer);
+   xmlFreeTextWriter(writer);
+
+   result = xmlBuffer_to_xmltype(buf);
+   xmlBufferFree(buf);
+   return result;
+#else
+   NO_XML_SUPPORT();
+   return NULL;
+#endif
+}
+
+
 xmltype *
 xmlparse(text *data, bool is_document, bool preserve_whitespace)
 {
@@ -313,6 +380,7 @@ xmltype *
 xmlroot(xmltype *data, text *version, int standalone)
 {
 #ifdef USE_LIBXML
+   xmltype    *result;
    xmlDocPtr   doc;
    xmlBufferPtr buffer;
    xmlSaveCtxtPtr save;
@@ -344,7 +412,9 @@ xmlroot(xmltype *data, text *version, int standalone)
 
    xmlFreeDoc(doc);
 
-   return xmlBuffer_to_xmltype(buffer);
+   result = xmlBuffer_to_xmltype(buffer);
+   xmlBufferFree(buffer);
+   return result;
 #else
    NO_XML_SUPPORT();
    return NULL;
index 4d98f1791244bcec7be27de14cd8104525a2e6f9..c4e508c488d140e1d7551bec6015ccf08afa5cd8 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/xml.h,v 1.7 2007/01/07 22:49:56 petere Exp $
+ * $PostgreSQL: pgsql/src/include/utils/xml.h,v 1.8 2007/01/10 20:33:54 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -16,6 +16,7 @@
 #define XML_H
 
 #include "fmgr.h"
+#include "nodes/execnodes.h"
 
 typedef struct varlena xmltype;
 
@@ -32,6 +33,7 @@ extern Datum xmlcomment(PG_FUNCTION_ARGS);
 extern Datum texttoxml(PG_FUNCTION_ARGS);
 extern Datum xmlvalidate(PG_FUNCTION_ARGS);
 
+extern xmltype *xmlelement(XmlExprState *xmlExpr, ExprContext *econtext);
 extern xmltype *xmlparse(text *data, bool is_doc, bool preserve_whitespace);
 extern xmltype *xmlpi(char *target, text *arg, bool arg_is_null, bool *result_is_null);
 extern xmltype *xmlroot(xmltype *data, text *version, int standalone);