From: Peter Eisentraut Date: Wed, 10 Jan 2007 20:33:54 +0000 (+0000) Subject: Use libxml's xmlwriter API for producing XML elements, instead of doing X-Git-Tag: REL8_3_BETA1~1545 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c0e977c18f1939cb0d948c51740aa8816d69c720;p=postgresql Use libxml's xmlwriter API for producing XML elements, instead of doing our own printing dance. This does a better job of quoting and escaping the values. --- diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c index c23680f11b..994f7d57ac 100644 --- a/src/backend/executor/execQual.c +++ b/src/backend/executor/execQual.c @@ -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, "", 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; diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c index 5137834efb..5616259b29 100644 --- a/src/backend/utils/adt/xml.c +++ b/src/backend/utils/adt/xml.c @@ -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 $ * *------------------------------------------------------------------------- */ @@ -32,8 +32,10 @@ #include #include #include +#include #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; diff --git a/src/include/utils/xml.h b/src/include/utils/xml.h index 4d98f17912..c4e508c488 100644 --- a/src/include/utils/xml.h +++ b/src/include/utils/xml.h @@ -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);