OSDN Git Service

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 c23680f..994f7d5 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 5137834..5616259 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"
@@ -240,6 +242,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)
 {
 #ifdef USE_LIBXML
@@ -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 4d98f17..c4e508c 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);