PostgreSQL Source Code git master
xml.h File Reference
#include "executor/tablefunc.h"
#include "fmgr.h"
#include "nodes/execnodes.h"
#include "nodes/primnodes.h"
Include dependency graph for xml.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define PG_GETARG_XML_P(n)   DatumGetXmlP(PG_GETARG_DATUM(n))
 
#define PG_RETURN_XML_P(x)   PG_RETURN_POINTER(x)
 

Typedefs

typedef struct varlena xmltype
 
typedef struct PgXmlErrorContext PgXmlErrorContext
 

Enumerations

enum  XmlStandaloneType { XML_STANDALONE_YES , XML_STANDALONE_NO , XML_STANDALONE_NO_VALUE , XML_STANDALONE_OMITTED }
 
enum  XmlBinaryType { XMLBINARY_BASE64 , XMLBINARY_HEX }
 
enum  PgXmlStrictness { PG_XML_STRICTNESS_LEGACY , PG_XML_STRICTNESS_WELLFORMED , PG_XML_STRICTNESS_ALL }
 

Functions

static xmltypeDatumGetXmlP (Datum X)
 
static Datum XmlPGetDatum (const xmltype *X)
 
void pg_xml_init_library (void)
 
PgXmlErrorContextpg_xml_init (PgXmlStrictness strictness)
 
void pg_xml_done (PgXmlErrorContext *errcxt, bool isError)
 
bool pg_xml_error_occurred (PgXmlErrorContext *errcxt)
 
void xml_ereport (PgXmlErrorContext *errcxt, int level, int sqlcode, const char *msg)
 
xmltypexmlconcat (List *args)
 
xmltypexmlelement (XmlExpr *xexpr, Datum *named_argvalue, bool *named_argnull, Datum *argvalue, bool *argnull)
 
xmltypexmlparse (text *data, XmlOptionType xmloption_arg, bool preserve_whitespace)
 
xmltypexmlpi (const char *target, text *arg, bool arg_is_null, bool *result_is_null)
 
xmltypexmlroot (xmltype *data, text *version, int standalone)
 
bool xml_is_document (xmltype *arg)
 
textxmltotext_with_options (xmltype *data, XmlOptionType xmloption_arg, bool indent)
 
char * escape_xml (const char *str)
 
char * map_sql_identifier_to_xml_name (const char *ident, bool fully_escaped, bool escape_period)
 
char * map_xml_name_to_sql_identifier (const char *name)
 
char * map_sql_value_to_xml_value (Datum value, Oid type, bool xml_escape_strings)
 

Variables

PGDLLIMPORT int xmlbinary
 
PGDLLIMPORT int xmloption
 
PGDLLIMPORT const TableFuncRoutine XmlTableRoutine
 

Macro Definition Documentation

◆ PG_GETARG_XML_P

#define PG_GETARG_XML_P (   n)    DatumGetXmlP(PG_GETARG_DATUM(n))

Definition at line 62 of file xml.h.

◆ PG_RETURN_XML_P

#define PG_RETURN_XML_P (   x)    PG_RETURN_POINTER(x)

Definition at line 63 of file xml.h.

Typedef Documentation

◆ PgXmlErrorContext

Definition at line 48 of file xml.h.

◆ xmltype

typedef struct varlena xmltype

Definition at line 23 of file xml.h.

Enumeration Type Documentation

◆ PgXmlStrictness

Enumerator
PG_XML_STRICTNESS_LEGACY 
PG_XML_STRICTNESS_WELLFORMED 
PG_XML_STRICTNESS_ALL 

Definition at line 39 of file xml.h.

40{
41 PG_XML_STRICTNESS_LEGACY, /* ignore errors unless function result
42 * indicates error condition */
43 PG_XML_STRICTNESS_WELLFORMED, /* ignore non-parser messages */
44 PG_XML_STRICTNESS_ALL, /* report all notices/warnings/errors */
PgXmlStrictness
Definition: xml.h:40
@ PG_XML_STRICTNESS_LEGACY
Definition: xml.h:41
@ PG_XML_STRICTNESS_ALL
Definition: xml.h:44
@ PG_XML_STRICTNESS_WELLFORMED
Definition: xml.h:43

◆ XmlBinaryType

Enumerator
XMLBINARY_BASE64 
XMLBINARY_HEX 

Definition at line 33 of file xml.h.

34{
XmlBinaryType
Definition: xml.h:34
@ XMLBINARY_BASE64
Definition: xml.h:35
@ XMLBINARY_HEX
Definition: xml.h:36

◆ XmlStandaloneType

Enumerator
XML_STANDALONE_YES 
XML_STANDALONE_NO 
XML_STANDALONE_NO_VALUE 
XML_STANDALONE_OMITTED 

Definition at line 25 of file xml.h.

26{
XmlStandaloneType
Definition: xml.h:26
@ XML_STANDALONE_OMITTED
Definition: xml.h:30
@ XML_STANDALONE_NO_VALUE
Definition: xml.h:29
@ XML_STANDALONE_YES
Definition: xml.h:27
@ XML_STANDALONE_NO
Definition: xml.h:28

Function Documentation

◆ DatumGetXmlP()

static xmltype * DatumGetXmlP ( Datum  X)
inlinestatic

Definition at line 51 of file xml.h.

52{
53 return (xmltype *) PG_DETOAST_DATUM(X);
54}
#define PG_DETOAST_DATUM(datum)
Definition: fmgr.h:240
Definition: c.h:658

References PG_DETOAST_DATUM.

Referenced by ExecEvalXmlExpr(), xmlconcat(), and XmlTableSetDocument().

◆ escape_xml()

char * escape_xml ( const char *  str)

Definition at line 2708 of file xml.c.

2709{
2711 const char *p;
2712
2714 for (p = str; *p; p++)
2715 {
2716 switch (*p)
2717 {
2718 case '&':
2719 appendStringInfoString(&buf, "&");
2720 break;
2721 case '<':
2722 appendStringInfoString(&buf, "&lt;");
2723 break;
2724 case '>':
2725 appendStringInfoString(&buf, "&gt;");
2726 break;
2727 case '\r':
2728 appendStringInfoString(&buf, "&#x0d;");
2729 break;
2730 default:
2732 break;
2733 }
2734 }
2735 return buf.data;
2736}
const char * str
static char * buf
Definition: pg_test_fsync.c:72
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:230
void initStringInfo(StringInfo str)
Definition: stringinfo.c:97
#define appendStringInfoCharMacro(str, ch)
Definition: stringinfo.h:231

References appendStringInfoCharMacro, appendStringInfoString(), buf, initStringInfo(), and str.

Referenced by ExplainProperty(), ExplainPropertyList(), map_sql_value_to_xml_value(), and XmlTableGetValue().

◆ map_sql_identifier_to_xml_name()

char * map_sql_identifier_to_xml_name ( const char *  ident,
bool  fully_escaped,
bool  escape_period 
)

Definition at line 2391 of file xml.c.

2393{
2394#ifdef USE_LIBXML
2396 const char *p;
2397
2398 /*
2399 * SQL/XML doesn't make use of this case anywhere, so it's probably a
2400 * mistake.
2401 */
2402 Assert(fully_escaped || !escape_period);
2403
2405
2406 for (p = ident; *p; p += pg_mblen(p))
2407 {
2408 if (*p == ':' && (p == ident || fully_escaped))
2409 appendStringInfoString(&buf, "_x003A_");
2410 else if (*p == '_' && *(p + 1) == 'x')
2411 appendStringInfoString(&buf, "_x005F_");
2412 else if (fully_escaped && p == ident &&
2413 pg_strncasecmp(p, "xml", 3) == 0)
2414 {
2415 if (*p == 'x')
2416 appendStringInfoString(&buf, "_x0078_");
2417 else
2418 appendStringInfoString(&buf, "_x0058_");
2419 }
2420 else if (escape_period && *p == '.')
2421 appendStringInfoString(&buf, "_x002E_");
2422 else
2423 {
2424 pg_wchar u = sqlchar_to_unicode(p);
2425
2426 if ((p == ident)
2427 ? !is_valid_xml_namefirst(u)
2428 : !is_valid_xml_namechar(u))
2429 appendStringInfo(&buf, "_x%04X_", (unsigned int) u);
2430 else
2432 }
2433 }
2434
2435 return buf.data;
2436#else /* not USE_LIBXML */
2438 return NULL;
2439#endif /* not USE_LIBXML */
2440}
Assert(PointerIsAligned(start, uint64))
#define ident
Definition: indent_codes.h:47
unsigned int pg_wchar
Definition: mbprint.c:31
int pg_mblen(const char *mbstr)
Definition: mbutils.c:1024
int pg_strncasecmp(const char *s1, const char *s2, size_t n)
Definition: pgstrcasecmp.c:69
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:145
void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)
Definition: stringinfo.c:281
#define NO_XML_SUPPORT()
Definition: xml.c:235

References appendBinaryStringInfo(), appendStringInfo(), appendStringInfoString(), Assert(), buf, ident, initStringInfo(), NO_XML_SUPPORT, pg_mblen(), and pg_strncasecmp().

Referenced by database_to_xml_internal(), map_multipart_sql_identifier_to_xml_name(), map_sql_catalog_to_xmlschema_types(), map_sql_schema_to_xmlschema_types(), map_sql_table_to_xmlschema(), query_to_xml_internal(), schema_to_xml_internal(), SPI_sql_row_to_xmlelement(), and transformXmlExpr().

◆ map_sql_value_to_xml_value()

char * map_sql_value_to_xml_value ( Datum  value,
Oid  type,
bool  xml_escape_strings 
)

Definition at line 2489 of file xml.c.

2490{
2492 {
2493 ArrayType *array;
2494 Oid elmtype;
2495 int16 elmlen;
2496 bool elmbyval;
2497 char elmalign;
2498 int num_elems;
2499 Datum *elem_values;
2500 bool *elem_nulls;
2502 int i;
2503
2504 array = DatumGetArrayTypeP(value);
2505 elmtype = ARR_ELEMTYPE(array);
2506 get_typlenbyvalalign(elmtype, &elmlen, &elmbyval, &elmalign);
2507
2508 deconstruct_array(array, elmtype,
2509 elmlen, elmbyval, elmalign,
2510 &elem_values, &elem_nulls,
2511 &num_elems);
2512
2514
2515 for (i = 0; i < num_elems; i++)
2516 {
2517 if (elem_nulls[i])
2518 continue;
2519 appendStringInfoString(&buf, "<element>");
2521 map_sql_value_to_xml_value(elem_values[i],
2522 elmtype, true));
2523 appendStringInfoString(&buf, "</element>");
2524 }
2525
2526 pfree(elem_values);
2527 pfree(elem_nulls);
2528
2529 return buf.data;
2530 }
2531 else
2532 {
2533 Oid typeOut;
2534 bool isvarlena;
2535 char *str;
2536
2537 /*
2538 * Flatten domains; the special-case treatments below should apply to,
2539 * eg, domains over boolean not just boolean.
2540 */
2542
2543 /*
2544 * Special XSD formatting for some data types
2545 */
2546 switch (type)
2547 {
2548 case BOOLOID:
2549 if (DatumGetBool(value))
2550 return "true";
2551 else
2552 return "false";
2553
2554 case DATEOID:
2555 {
2556 DateADT date;
2557 struct pg_tm tm;
2558 char buf[MAXDATELEN + 1];
2559
2561 /* XSD doesn't support infinite values */
2562 if (DATE_NOT_FINITE(date))
2563 ereport(ERROR,
2564 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2565 errmsg("date out of range"),
2566 errdetail("XML does not support infinite date values.")));
2568 &(tm.tm_year), &(tm.tm_mon), &(tm.tm_mday));
2570
2571 return pstrdup(buf);
2572 }
2573
2574 case TIMESTAMPOID:
2575 {
2577 struct pg_tm tm;
2578 fsec_t fsec;
2579 char buf[MAXDATELEN + 1];
2580
2582
2583 /* XSD doesn't support infinite values */
2585 ereport(ERROR,
2586 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2587 errmsg("timestamp out of range"),
2588 errdetail("XML does not support infinite timestamp values.")));
2589 else if (timestamp2tm(timestamp, NULL, &tm, &fsec, NULL, NULL) == 0)
2590 EncodeDateTime(&tm, fsec, false, 0, NULL, USE_XSD_DATES, buf);
2591 else
2592 ereport(ERROR,
2593 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2594 errmsg("timestamp out of range")));
2595
2596 return pstrdup(buf);
2597 }
2598
2599 case TIMESTAMPTZOID:
2600 {
2602 struct pg_tm tm;
2603 int tz;
2604 fsec_t fsec;
2605 const char *tzn = NULL;
2606 char buf[MAXDATELEN + 1];
2607
2609
2610 /* XSD doesn't support infinite values */
2612 ereport(ERROR,
2613 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2614 errmsg("timestamp out of range"),
2615 errdetail("XML does not support infinite timestamp values.")));
2616 else if (timestamp2tm(timestamp, &tz, &tm, &fsec, &tzn, NULL) == 0)
2617 EncodeDateTime(&tm, fsec, true, tz, tzn, USE_XSD_DATES, buf);
2618 else
2619 ereport(ERROR,
2620 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2621 errmsg("timestamp out of range")));
2622
2623 return pstrdup(buf);
2624 }
2625
2626#ifdef USE_LIBXML
2627 case BYTEAOID:
2628 {
2629 bytea *bstr = DatumGetByteaPP(value);
2630 PgXmlErrorContext *xmlerrcxt;
2631 volatile xmlBufferPtr buf = NULL;
2632 volatile xmlTextWriterPtr writer = NULL;
2633 char *result;
2634
2636
2637 PG_TRY();
2638 {
2639 buf = xmlBufferCreate();
2640 if (buf == NULL || xmlerrcxt->err_occurred)
2641 xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
2642 "could not allocate xmlBuffer");
2643 writer = xmlNewTextWriterMemory(buf, 0);
2644 if (writer == NULL || xmlerrcxt->err_occurred)
2645 xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
2646 "could not allocate xmlTextWriter");
2647
2649 xmlTextWriterWriteBase64(writer, VARDATA_ANY(bstr),
2650 0, VARSIZE_ANY_EXHDR(bstr));
2651 else
2652 xmlTextWriterWriteBinHex(writer, VARDATA_ANY(bstr),
2653 0, VARSIZE_ANY_EXHDR(bstr));
2654
2655 /* we MUST do this now to flush data out to the buffer */
2656 xmlFreeTextWriter(writer);
2657 writer = NULL;
2658
2659 result = pstrdup((const char *) xmlBufferContent(buf));
2660 }
2661 PG_CATCH();
2662 {
2663 if (writer)
2664 xmlFreeTextWriter(writer);
2665 if (buf)
2666 xmlBufferFree(buf);
2667
2668 pg_xml_done(xmlerrcxt, true);
2669
2670 PG_RE_THROW();
2671 }
2672 PG_END_TRY();
2673
2674 xmlBufferFree(buf);
2675
2676 pg_xml_done(xmlerrcxt, false);
2677
2678 return result;
2679 }
2680#endif /* USE_LIBXML */
2681
2682 }
2683
2684 /*
2685 * otherwise, just use the type's native text representation
2686 */
2687 getTypeOutputInfo(type, &typeOut, &isvarlena);
2688 str = OidOutputFunctionCall(typeOut, value);
2689
2690 /* ... exactly as-is for XML, and when escaping is not wanted */
2691 if (type == XMLOID || !xml_escape_strings)
2692 return str;
2693
2694 /* otherwise, translate special characters as needed */
2695 return escape_xml(str);
2696 }
2697}
#define DatumGetArrayTypeP(X)
Definition: array.h:261
#define ARR_ELEMTYPE(a)
Definition: array.h:292
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3631
void j2date(int jd, int *year, int *month, int *day)
Definition: datetime.c:321
void EncodeDateTime(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, const char *tzn, int style, char *str)
Definition: datetime.c:4458
void EncodeDateOnly(struct pg_tm *tm, int style, char *str)
Definition: datetime.c:4343
int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
Definition: timestamp.c:1910
int16_t int16
Definition: c.h:497
int64 Timestamp
Definition: timestamp.h:38
int64 TimestampTz
Definition: timestamp.h:39
int32 fsec_t
Definition: timestamp.h:41
#define TIMESTAMP_NOT_FINITE(j)
Definition: timestamp.h:169
#define POSTGRES_EPOCH_JDATE
Definition: timestamp.h:235
#define DATE_NOT_FINITE(j)
Definition: date.h:43
int32 DateADT
Definition: date.h:23
static DateADT DatumGetDateADT(Datum X)
Definition: date.h:54
int errdetail(const char *fmt,...)
Definition: elog.c:1204
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#define PG_RE_THROW()
Definition: elog.h:404
#define PG_TRY(...)
Definition: elog.h:371
#define PG_END_TRY(...)
Definition: elog.h:396
#define ERROR
Definition: elog.h:39
#define PG_CATCH(...)
Definition: elog.h:381
#define ereport(elevel,...)
Definition: elog.h:149
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1763
#define DatumGetByteaPP(X)
Definition: fmgr.h:291
#define MAXDATELEN
Definition: datetime.h:200
static struct @165 value
int i
Definition: isn.c:77
static struct pg_tm tm
Definition: localtime.c:104
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:3047
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2411
Oid getBaseType(Oid typid)
Definition: lsyscache.c:2661
#define type_is_array_domain(typid)
Definition: lsyscache.h:216
char * pstrdup(const char *in)
Definition: mcxt.c:1703
void pfree(void *pointer)
Definition: mcxt.c:1528
#define USE_XSD_DATES
Definition: miscadmin.h:239
long date
Definition: pgtypes_date.h:9
int64 timestamp
static bool DatumGetBool(Datum X)
Definition: postgres.h:95
uintptr_t Datum
Definition: postgres.h:69
unsigned int Oid
Definition: postgres_ext.h:30
Definition: pgtime.h:35
int tm_mday
Definition: pgtime.h:39
int tm_mon
Definition: pgtime.h:40
int tm_year
Definition: pgtime.h:41
static Timestamp DatumGetTimestamp(Datum X)
Definition: timestamp.h:28
#define VARDATA_ANY(PTR)
Definition: varatt.h:324
#define VARSIZE_ANY_EXHDR(PTR)
Definition: varatt.h:317
const char * type
int xmlbinary
Definition: xml.c:109
char * map_sql_value_to_xml_value(Datum value, Oid type, bool xml_escape_strings)
Definition: xml.c:2489
char * escape_xml(const char *str)
Definition: xml.c:2708
struct PgXmlErrorContext PgXmlErrorContext
Definition: xml.h:48
PgXmlErrorContext * pg_xml_init(PgXmlStrictness strictness)
void xml_ereport(PgXmlErrorContext *errcxt, int level, int sqlcode, const char *msg)
void pg_xml_done(PgXmlErrorContext *errcxt, bool isError)

References appendStringInfoString(), ARR_ELEMTYPE, buf, DATE_NOT_FINITE, DatumGetArrayTypeP, DatumGetBool(), DatumGetByteaPP, DatumGetDateADT(), DatumGetTimestamp(), deconstruct_array(), EncodeDateOnly(), EncodeDateTime(), ereport, errcode(), errdetail(), errmsg(), ERROR, escape_xml(), get_typlenbyvalalign(), getBaseType(), getTypeOutputInfo(), i, initStringInfo(), j2date(), map_sql_value_to_xml_value(), MAXDATELEN, OidOutputFunctionCall(), pfree(), PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, pg_xml_done(), pg_xml_init(), PG_XML_STRICTNESS_ALL, POSTGRES_EPOCH_JDATE, pstrdup(), str, timestamp2tm(), TIMESTAMP_NOT_FINITE, tm, pg_tm::tm_mday, pg_tm::tm_mon, pg_tm::tm_year, type, type_is_array_domain, USE_XSD_DATES, value, VARDATA_ANY, VARSIZE_ANY_EXHDR, xml_ereport(), xmlbinary, and XMLBINARY_BASE64.

Referenced by ExecEvalXmlExpr(), map_sql_value_to_xml_value(), SPI_sql_row_to_xmlelement(), and xmlelement().

◆ map_xml_name_to_sql_identifier()

char * map_xml_name_to_sql_identifier ( const char *  name)

Definition at line 2447 of file xml.c.

2448{
2450 const char *p;
2451
2453
2454 for (p = name; *p; p += pg_mblen(p))
2455 {
2456 if (*p == '_' && *(p + 1) == 'x'
2457 && isxdigit((unsigned char) *(p + 2))
2458 && isxdigit((unsigned char) *(p + 3))
2459 && isxdigit((unsigned char) *(p + 4))
2460 && isxdigit((unsigned char) *(p + 5))
2461 && *(p + 6) == '_')
2462 {
2463 char cbuf[MAX_UNICODE_EQUIVALENT_STRING + 1];
2464 unsigned int u;
2465
2466 sscanf(p + 2, "%X", &u);
2467 pg_unicode_to_server(u, (unsigned char *) cbuf);
2469 p += 6;
2470 }
2471 else
2473 }
2474
2475 return buf.data;
2476}
void pg_unicode_to_server(pg_wchar c, unsigned char *s)
Definition: mbutils.c:865
#define MAX_UNICODE_EQUIVALENT_STRING
Definition: pg_wchar.h:329
const char * name

References appendBinaryStringInfo(), appendStringInfoString(), buf, initStringInfo(), MAX_UNICODE_EQUIVALENT_STRING, name, pg_mblen(), and pg_unicode_to_server().

Referenced by get_rule_expr().

◆ pg_xml_done()

◆ pg_xml_error_occurred()

bool pg_xml_error_occurred ( PgXmlErrorContext errcxt)

◆ pg_xml_init()

◆ pg_xml_init_library()

void pg_xml_init_library ( void  )

◆ xml_ereport()

◆ xml_is_document()

bool xml_is_document ( xmltype arg)

Definition at line 1124 of file xml.c.

1125{
1126#ifdef USE_LIBXML
1127 xmlDocPtr doc;
1128 ErrorSaveContext escontext = {T_ErrorSaveContext};
1129
1130 /*
1131 * We'll report "true" if no soft error is reported by xml_parse().
1132 */
1133 doc = xml_parse((text *) arg, XMLOPTION_DOCUMENT, true,
1134 GetDatabaseEncoding(), NULL, NULL, (Node *) &escontext);
1135 if (doc)
1136 xmlFreeDoc(doc);
1137
1138 return !escontext.error_occurred;
1139#else /* not USE_LIBXML */
1141 return false;
1142#endif /* not USE_LIBXML */
1143}
int GetDatabaseEncoding(void)
Definition: mbutils.c:1262
void * arg
@ XMLOPTION_DOCUMENT
Definition: primnodes.h:1597
bool error_occurred
Definition: miscnodes.h:47
Definition: nodes.h:135

References arg, ErrorSaveContext::error_occurred, GetDatabaseEncoding(), NO_XML_SUPPORT, and XMLOPTION_DOCUMENT.

Referenced by ExecEvalXmlExpr().

◆ xmlconcat()

xmltype * xmlconcat ( List args)

Definition at line 553 of file xml.c.

554{
555#ifdef USE_LIBXML
556 int global_standalone = 1;
557 xmlChar *global_version = NULL;
558 bool global_version_no_value = false;
560 ListCell *v;
561
563 foreach(v, args)
564 {
566 size_t len;
567 xmlChar *version;
568 int standalone;
569 char *str;
570
571 len = VARSIZE(x) - VARHDRSZ;
572 str = text_to_cstring((text *) x);
573
574 parse_xml_decl((xmlChar *) str, &len, &version, NULL, &standalone);
575
576 if (standalone == 0 && global_standalone == 1)
577 global_standalone = 0;
578 if (standalone < 0)
579 global_standalone = -1;
580
581 if (!version)
582 global_version_no_value = true;
583 else if (!global_version)
584 global_version = version;
585 else if (xmlStrcmp(version, global_version) != 0)
586 global_version_no_value = true;
587
589 pfree(str);
590 }
591
592 if (!global_version_no_value || global_standalone >= 0)
593 {
594 StringInfoData buf2;
595
596 initStringInfo(&buf2);
597
598 print_xml_decl(&buf2,
599 (!global_version_no_value) ? global_version : NULL,
600 0,
601 global_standalone);
602
603 appendBinaryStringInfo(&buf2, buf.data, buf.len);
604 buf = buf2;
605 }
606
607 return stringinfo_to_xmltype(&buf);
608#else
610 return NULL;
611#endif
612}
#define VARHDRSZ
Definition: c.h:663
int x
Definition: isn.c:75
const void size_t len
#define lfirst(lc)
Definition: pg_list.h:172
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:327
#define VARSIZE(PTR)
Definition: varatt.h:279
char * text_to_cstring(const text *t)
Definition: varlena.c:225
static xmltype * stringinfo_to_xmltype(StringInfo buf)
Definition: xml.c:467
static xmltype * DatumGetXmlP(Datum X)
Definition: xml.h:51

References appendBinaryStringInfo(), appendStringInfoString(), generate_unaccent_rules::args, buf, DatumGetXmlP(), initStringInfo(), len, lfirst, NO_XML_SUPPORT, pfree(), PointerGetDatum(), str, stringinfo_to_xmltype(), text_to_cstring(), VARHDRSZ, VARSIZE, and x.

Referenced by ExecEvalXmlExpr(), and xmlconcat2().

◆ xmlelement()

xmltype * xmlelement ( XmlExpr xexpr,
Datum named_argvalue,
bool *  named_argnull,
Datum argvalue,
bool *  argnull 
)

Definition at line 864 of file xml.c.

867{
868#ifdef USE_LIBXML
869 xmltype *result;
870 List *named_arg_strings;
871 List *arg_strings;
872 int i;
873 ListCell *arg;
874 ListCell *narg;
875 PgXmlErrorContext *xmlerrcxt;
876 volatile xmlBufferPtr buf = NULL;
877 volatile xmlTextWriterPtr writer = NULL;
878
879 /*
880 * All arguments are already evaluated, and their values are passed in the
881 * named_argvalue/named_argnull or argvalue/argnull arrays. This avoids
882 * issues if one of the arguments involves a call to some other function
883 * or subsystem that wants to use libxml on its own terms. We examine the
884 * original XmlExpr to identify the numbers and types of the arguments.
885 */
886 named_arg_strings = NIL;
887 i = 0;
888 foreach(arg, xexpr->named_args)
889 {
890 Expr *e = (Expr *) lfirst(arg);
891 char *str;
892
893 if (named_argnull[i])
894 str = NULL;
895 else
896 str = map_sql_value_to_xml_value(named_argvalue[i],
897 exprType((Node *) e),
898 false);
899 named_arg_strings = lappend(named_arg_strings, str);
900 i++;
901 }
902
903 arg_strings = NIL;
904 i = 0;
905 foreach(arg, xexpr->args)
906 {
907 Expr *e = (Expr *) lfirst(arg);
908 char *str;
909
910 /* here we can just forget NULL elements immediately */
911 if (!argnull[i])
912 {
913 str = map_sql_value_to_xml_value(argvalue[i],
914 exprType((Node *) e),
915 true);
916 arg_strings = lappend(arg_strings, str);
917 }
918 i++;
919 }
920
922
923 PG_TRY();
924 {
925 buf = xmlBufferCreate();
926 if (buf == NULL || xmlerrcxt->err_occurred)
927 xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
928 "could not allocate xmlBuffer");
929 writer = xmlNewTextWriterMemory(buf, 0);
930 if (writer == NULL || xmlerrcxt->err_occurred)
931 xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
932 "could not allocate xmlTextWriter");
933
934 xmlTextWriterStartElement(writer, (xmlChar *) xexpr->name);
935
936 forboth(arg, named_arg_strings, narg, xexpr->arg_names)
937 {
938 char *str = (char *) lfirst(arg);
939 char *argname = strVal(lfirst(narg));
940
941 if (str)
942 xmlTextWriterWriteAttribute(writer,
943 (xmlChar *) argname,
944 (xmlChar *) str);
945 }
946
947 foreach(arg, arg_strings)
948 {
949 char *str = (char *) lfirst(arg);
950
951 xmlTextWriterWriteRaw(writer, (xmlChar *) str);
952 }
953
954 xmlTextWriterEndElement(writer);
955
956 /* we MUST do this now to flush data out to the buffer ... */
957 xmlFreeTextWriter(writer);
958 writer = NULL;
959
960 result = xmlBuffer_to_xmltype(buf);
961 }
962 PG_CATCH();
963 {
964 if (writer)
965 xmlFreeTextWriter(writer);
966 if (buf)
967 xmlBufferFree(buf);
968
969 pg_xml_done(xmlerrcxt, true);
970
971 PG_RE_THROW();
972 }
973 PG_END_TRY();
974
975 xmlBufferFree(buf);
976
977 pg_xml_done(xmlerrcxt, false);
978
979 return result;
980#else
982 return NULL;
983#endif
984}
List * lappend(List *list, void *datum)
Definition: list.c:339
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
#define NIL
Definition: pg_list.h:68
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:518
e
Definition: preproc-init.c:82
Definition: pg_list.h:54
List * args
Definition: primnodes.h:1613
List * named_args
Definition: primnodes.h:1609
#define strVal(v)
Definition: value.h:82

References arg, XmlExpr::args, buf, ERROR, exprType(), forboth, i, lappend(), lfirst, map_sql_value_to_xml_value(), XmlExpr::named_args, NIL, NO_XML_SUPPORT, PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, pg_xml_done(), pg_xml_init(), PG_XML_STRICTNESS_ALL, str, strVal, and xml_ereport().

Referenced by ExecEvalXmlExpr().

◆ xmlparse()

xmltype * xmlparse ( text data,
XmlOptionType  xmloption_arg,
bool  preserve_whitespace 
)

Definition at line 988 of file xml.c.

989{
990#ifdef USE_LIBXML
991 xmlDocPtr doc;
992
993 doc = xml_parse(data, xmloption_arg, preserve_whitespace,
994 GetDatabaseEncoding(), NULL, NULL, NULL);
995 xmlFreeDoc(doc);
996
997 return (xmltype *) data;
998#else
1000 return NULL;
1001#endif
1002}
const void * data

References data, GetDatabaseEncoding(), and NO_XML_SUPPORT.

Referenced by ExecEvalXmlExpr(), and texttoxml().

◆ XmlPGetDatum()

static Datum XmlPGetDatum ( const xmltype X)
inlinestatic

Definition at line 57 of file xml.h.

58{
59 return PointerGetDatum(X);
60}

References PointerGetDatum().

◆ xmlpi()

xmltype * xmlpi ( const char *  target,
text arg,
bool  arg_is_null,
bool *  result_is_null 
)

Definition at line 1006 of file xml.c.

1007{
1008#ifdef USE_LIBXML
1009 xmltype *result;
1011
1012 if (pg_strcasecmp(target, "xml") == 0)
1013 ereport(ERROR,
1014 (errcode(ERRCODE_INVALID_XML_PROCESSING_INSTRUCTION),
1015 errmsg("invalid XML processing instruction"),
1016 errdetail("XML processing instruction target name cannot be \"%s\".", target)));
1017
1018 /*
1019 * Following the SQL standard, the null check comes after the syntax check
1020 * above.
1021 */
1022 *result_is_null = arg_is_null;
1023 if (*result_is_null)
1024 return NULL;
1025
1027
1028 appendStringInfo(&buf, "<?%s", target);
1029
1030 if (arg != NULL)
1031 {
1032 char *string;
1033
1034 string = text_to_cstring(arg);
1035 if (strstr(string, "?>") != NULL)
1036 ereport(ERROR,
1037 (errcode(ERRCODE_INVALID_XML_PROCESSING_INSTRUCTION),
1038 errmsg("invalid XML processing instruction"),
1039 errdetail("XML processing instruction cannot contain \"?>\".")));
1040
1042 appendStringInfoString(&buf, string + strspn(string, " "));
1043 pfree(string);
1044 }
1046
1047 result = stringinfo_to_xmltype(&buf);
1048 pfree(buf.data);
1049 return result;
1050#else
1052 return NULL;
1053#endif
1054}
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
char string[11]
Definition: preproc-type.c:52
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:242

References appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), arg, buf, ereport, errcode(), errdetail(), errmsg(), ERROR, initStringInfo(), NO_XML_SUPPORT, pfree(), pg_strcasecmp(), stringinfo_to_xmltype(), and text_to_cstring().

Referenced by ExecEvalXmlExpr().

◆ xmlroot()

xmltype * xmlroot ( xmltype data,
text version,
int  standalone 
)

Definition at line 1058 of file xml.c.

1059{
1060#ifdef USE_LIBXML
1061 char *str;
1062 size_t len;
1063 xmlChar *orig_version;
1064 int orig_standalone;
1066
1067 len = VARSIZE(data) - VARHDRSZ;
1069
1070 parse_xml_decl((xmlChar *) str, &len, &orig_version, NULL, &orig_standalone);
1071
1072 if (version)
1073 orig_version = xml_text2xmlChar(version);
1074 else
1075 orig_version = NULL;
1076
1077 switch (standalone)
1078 {
1079 case XML_STANDALONE_YES:
1080 orig_standalone = 1;
1081 break;
1082 case XML_STANDALONE_NO:
1083 orig_standalone = 0;
1084 break;
1086 orig_standalone = -1;
1087 break;
1089 /* leave original value */
1090 break;
1091 }
1092
1094 print_xml_decl(&buf, orig_version, 0, orig_standalone);
1096
1097 return stringinfo_to_xmltype(&buf);
1098#else
1100 return NULL;
1101#endif
1102}

References appendStringInfoString(), buf, data, initStringInfo(), len, NO_XML_SUPPORT, str, stringinfo_to_xmltype(), text_to_cstring(), VARHDRSZ, VARSIZE, XML_STANDALONE_NO, XML_STANDALONE_NO_VALUE, XML_STANDALONE_OMITTED, and XML_STANDALONE_YES.

Referenced by ExecEvalXmlExpr().

◆ xmltotext_with_options()

text * xmltotext_with_options ( xmltype data,
XmlOptionType  xmloption_arg,
bool  indent 
)

Definition at line 656 of file xml.c.

657{
658#ifdef USE_LIBXML
659 text *volatile result;
660 xmlDocPtr doc;
661 XmlOptionType parsed_xmloptiontype;
662 xmlNodePtr content_nodes;
663 volatile xmlBufferPtr buf = NULL;
664 volatile xmlSaveCtxtPtr ctxt = NULL;
665 ErrorSaveContext escontext = {T_ErrorSaveContext};
666 PgXmlErrorContext *xmlerrcxt;
667#endif
668
669 if (xmloption_arg != XMLOPTION_DOCUMENT && !indent)
670 {
671 /*
672 * We don't actually need to do anything, so just return the
673 * binary-compatible input. For backwards-compatibility reasons,
674 * allow such cases to succeed even without USE_LIBXML.
675 */
676 return (text *) data;
677 }
678
679#ifdef USE_LIBXML
680
681 /*
682 * Parse the input according to the xmloption.
683 *
684 * preserve_whitespace is set to false in case we are indenting, otherwise
685 * libxml2 will fail to indent elements that have whitespace between them.
686 */
687 doc = xml_parse(data, xmloption_arg, !indent, GetDatabaseEncoding(),
688 &parsed_xmloptiontype, &content_nodes,
689 (Node *) &escontext);
690 if (doc == NULL || escontext.error_occurred)
691 {
692 if (doc)
693 xmlFreeDoc(doc);
694 /* A soft error must be failure to conform to XMLOPTION_DOCUMENT */
696 (errcode(ERRCODE_NOT_AN_XML_DOCUMENT),
697 errmsg("not an XML document")));
698 }
699
700 /* If we weren't asked to indent, we're done. */
701 if (!indent)
702 {
703 xmlFreeDoc(doc);
704 return (text *) data;
705 }
706
707 /* Otherwise, we gotta spin up some error handling. */
709
710 PG_TRY();
711 {
712 size_t decl_len = 0;
713
714 /* The serialized data will go into this buffer. */
715 buf = xmlBufferCreate();
716
717 if (buf == NULL || xmlerrcxt->err_occurred)
718 xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
719 "could not allocate xmlBuffer");
720
721 /* Detect whether there's an XML declaration */
722 parse_xml_decl(xml_text2xmlChar(data), &decl_len, NULL, NULL, NULL);
723
724 /*
725 * Emit declaration only if the input had one. Note: some versions of
726 * xmlSaveToBuffer leak memory if a non-null encoding argument is
727 * passed, so don't do that. We don't want any encoding conversion
728 * anyway.
729 */
730 if (decl_len == 0)
731 ctxt = xmlSaveToBuffer(buf, NULL,
732 XML_SAVE_NO_DECL | XML_SAVE_FORMAT);
733 else
734 ctxt = xmlSaveToBuffer(buf, NULL,
735 XML_SAVE_FORMAT);
736
737 if (ctxt == NULL || xmlerrcxt->err_occurred)
738 xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
739 "could not allocate xmlSaveCtxt");
740
741 if (parsed_xmloptiontype == XMLOPTION_DOCUMENT)
742 {
743 /* If it's a document, saving is easy. */
744 if (xmlSaveDoc(ctxt, doc) == -1 || xmlerrcxt->err_occurred)
745 xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
746 "could not save document to xmlBuffer");
747 }
748 else if (content_nodes != NULL)
749 {
750 /*
751 * Deal with the case where we have non-singly-rooted XML.
752 * libxml's dump functions don't work well for that without help.
753 * We build a fake root node that serves as a container for the
754 * content nodes, and then iterate over the nodes.
755 */
756 xmlNodePtr root;
757 xmlNodePtr oldroot;
758 xmlNodePtr newline;
759
760 root = xmlNewNode(NULL, (const xmlChar *) "content-root");
761 if (root == NULL || xmlerrcxt->err_occurred)
762 xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
763 "could not allocate xml node");
764
765 /*
766 * This attaches root to doc, so we need not free it separately...
767 * but instead, we have to free the old root if there was one.
768 */
769 oldroot = xmlDocSetRootElement(doc, root);
770 if (oldroot != NULL)
771 xmlFreeNode(oldroot);
772
773 xmlAddChildList(root, content_nodes);
774
775 /*
776 * We use this node to insert newlines in the dump. Note: in at
777 * least some libxml versions, xmlNewDocText would not attach the
778 * node to the document even if we passed it. Therefore, manage
779 * freeing of this node manually, and pass NULL here to make sure
780 * there's not a dangling link.
781 */
782 newline = xmlNewDocText(NULL, (const xmlChar *) "\n");
783 if (newline == NULL || xmlerrcxt->err_occurred)
784 xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
785 "could not allocate xml node");
786
787 for (xmlNodePtr node = root->children; node; node = node->next)
788 {
789 /* insert newlines between nodes */
790 if (node->type != XML_TEXT_NODE && node->prev != NULL)
791 {
792 if (xmlSaveTree(ctxt, newline) == -1 || xmlerrcxt->err_occurred)
793 {
794 xmlFreeNode(newline);
795 xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
796 "could not save newline to xmlBuffer");
797 }
798 }
799
800 if (xmlSaveTree(ctxt, node) == -1 || xmlerrcxt->err_occurred)
801 {
802 xmlFreeNode(newline);
803 xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
804 "could not save content to xmlBuffer");
805 }
806 }
807
808 xmlFreeNode(newline);
809 }
810
811 if (xmlSaveClose(ctxt) == -1 || xmlerrcxt->err_occurred)
812 {
813 ctxt = NULL; /* don't try to close it again */
814 xml_ereport(xmlerrcxt, ERROR, ERRCODE_INTERNAL_ERROR,
815 "could not close xmlSaveCtxtPtr");
816 }
817
818 /*
819 * xmlDocContentDumpOutput may add a trailing newline, so remove that.
820 */
821 if (xmloption_arg == XMLOPTION_DOCUMENT)
822 {
823 const char *str = (const char *) xmlBufferContent(buf);
824 int len = xmlBufferLength(buf);
825
826 while (len > 0 && (str[len - 1] == '\n' ||
827 str[len - 1] == '\r'))
828 len--;
829
831 }
832 else
833 result = (text *) xmlBuffer_to_xmltype(buf);
834 }
835 PG_CATCH();
836 {
837 if (ctxt)
838 xmlSaveClose(ctxt);
839 if (buf)
840 xmlBufferFree(buf);
841 if (doc)
842 xmlFreeDoc(doc);
843
844 pg_xml_done(xmlerrcxt, true);
845
846 PG_RE_THROW();
847 }
848 PG_END_TRY();
849
850 xmlBufferFree(buf);
851 xmlFreeDoc(doc);
852
853 pg_xml_done(xmlerrcxt, false);
854
855 return result;
856#else
858 return NULL;
859#endif
860}
#define newline
Definition: indent_codes.h:35
XmlOptionType
Definition: primnodes.h:1596
tree ctl root
Definition: radixtree.h:1857
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:204

References buf, cstring_to_text_with_len(), data, ereport, errcode(), errmsg(), ERROR, ErrorSaveContext::error_occurred, GetDatabaseEncoding(), len, newline, NO_XML_SUPPORT, PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, pg_xml_done(), pg_xml_init(), PG_XML_STRICTNESS_ALL, root, str, xml_ereport(), and XMLOPTION_DOCUMENT.

Referenced by ExecEvalXmlExpr().

Variable Documentation

◆ xmlbinary

PGDLLIMPORT int xmlbinary
extern

Definition at line 109 of file xml.c.

Referenced by map_sql_type_to_xmlschema_type(), and map_sql_value_to_xml_value().

◆ xmloption

PGDLLIMPORT int xmloption
extern

Definition at line 110 of file xml.c.

Referenced by texttoxml(), xml_in(), xml_is_well_formed(), and xml_recv().

◆ XmlTableRoutine

PGDLLIMPORT const TableFuncRoutine XmlTableRoutine
extern

Definition at line 223 of file xml.c.

Referenced by ExecInitTableFuncScan().