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.
This commit is contained in:
Peter Eisentraut 2007-01-10 20:33:54 +00:00
parent f21d5b61ce
commit c0e977c18f
3 changed files with 81 additions and 54 deletions

View 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;

View 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 $
*
*-------------------------------------------------------------------------
*/
@ -32,8 +32,10 @@
#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;

View 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);