mirror of
https://github.com/postgres/postgres.git
synced 2025-06-14 18:42:34 +03:00
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:
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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;
|
char *str;
|
||||||
ListCell *arg;
|
ListCell *arg;
|
||||||
ListCell *narg;
|
ListCell *narg;
|
||||||
bool found_arg;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (isDone)
|
if (isDone)
|
||||||
@ -2682,55 +2681,6 @@ ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
|
|||||||
}
|
}
|
||||||
break;
|
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:
|
case IS_XMLFOREST:
|
||||||
initStringInfo(&buf);
|
initStringInfo(&buf);
|
||||||
i = 0;
|
i = 0;
|
||||||
@ -2754,6 +2704,11 @@ ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
/* The remaining cases don't need to set up buf */
|
/* The remaining cases don't need to set up buf */
|
||||||
|
case IS_XMLELEMENT:
|
||||||
|
*isNull = false;
|
||||||
|
return PointerGetDatum(xmlelement(xmlExpr, econtext));
|
||||||
|
break;
|
||||||
|
|
||||||
case IS_XMLPARSE:
|
case IS_XMLPARSE:
|
||||||
{
|
{
|
||||||
ExprState *e;
|
ExprState *e;
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* 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/uri.h>
|
||||||
#include <libxml/xmlerror.h>
|
#include <libxml/xmlerror.h>
|
||||||
#include <libxml/xmlsave.h>
|
#include <libxml/xmlsave.h>
|
||||||
|
#include <libxml/xmlwriter.h>
|
||||||
#endif /* USE_LIBXML */
|
#endif /* USE_LIBXML */
|
||||||
|
|
||||||
|
#include "executor/executor.h"
|
||||||
#include "fmgr.h"
|
#include "fmgr.h"
|
||||||
#include "libpq/pqformat.h"
|
#include "libpq/pqformat.h"
|
||||||
#include "mb/pg_wchar.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 *
|
xmltype *
|
||||||
xmlparse(text *data, bool is_document, bool preserve_whitespace)
|
xmlparse(text *data, bool is_document, bool preserve_whitespace)
|
||||||
{
|
{
|
||||||
@ -313,6 +380,7 @@ xmltype *
|
|||||||
xmlroot(xmltype *data, text *version, int standalone)
|
xmlroot(xmltype *data, text *version, int standalone)
|
||||||
{
|
{
|
||||||
#ifdef USE_LIBXML
|
#ifdef USE_LIBXML
|
||||||
|
xmltype *result;
|
||||||
xmlDocPtr doc;
|
xmlDocPtr doc;
|
||||||
xmlBufferPtr buffer;
|
xmlBufferPtr buffer;
|
||||||
xmlSaveCtxtPtr save;
|
xmlSaveCtxtPtr save;
|
||||||
@ -344,7 +412,9 @@ xmlroot(xmltype *data, text *version, int standalone)
|
|||||||
|
|
||||||
xmlFreeDoc(doc);
|
xmlFreeDoc(doc);
|
||||||
|
|
||||||
return xmlBuffer_to_xmltype(buffer);
|
result = xmlBuffer_to_xmltype(buffer);
|
||||||
|
xmlBufferFree(buffer);
|
||||||
|
return result;
|
||||||
#else
|
#else
|
||||||
NO_XML_SUPPORT();
|
NO_XML_SUPPORT();
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* 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
|
#define XML_H
|
||||||
|
|
||||||
#include "fmgr.h"
|
#include "fmgr.h"
|
||||||
|
#include "nodes/execnodes.h"
|
||||||
|
|
||||||
typedef struct varlena xmltype;
|
typedef struct varlena xmltype;
|
||||||
|
|
||||||
@ -32,6 +33,7 @@ extern Datum xmlcomment(PG_FUNCTION_ARGS);
|
|||||||
extern Datum texttoxml(PG_FUNCTION_ARGS);
|
extern Datum texttoxml(PG_FUNCTION_ARGS);
|
||||||
extern Datum xmlvalidate(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 *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 *xmlpi(char *target, text *arg, bool arg_is_null, bool *result_is_null);
|
||||||
extern xmltype *xmlroot(xmltype *data, text *version, int standalone);
|
extern xmltype *xmlroot(xmltype *data, text *version, int standalone);
|
||||||
|
Reference in New Issue
Block a user