⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xml.c

📁 postgresql8.3.4源码,开源数据库
💻 C
📖 第 1 页 / 共 5 页
字号:
	return XML_ERR_OK;}/* * Write an XML declaration.  On output, we adjust the XML declaration * as follows.	(These rules are the moral equivalent of the clause * "Serialization of an XML value" in the SQL standard.) * * We try to avoid generating an XML declaration if possible.  This is * so that you don't get trivial things like xml '<foo/>' resulting in * '<?xml version="1.0"?><foo/>', which would surely be annoying.  We * must provide a declaration if the standalone property is specified * or if we include an encoding declaration.  If we have a * declaration, we must specify a version (XML requires this). * Otherwise we only make a declaration if the version is not "1.0", * which is the default version specified in SQL:2003. */static boolprint_xml_decl(StringInfo buf, const xmlChar * version,			   pg_enc encoding, int standalone){	xml_init();	if ((version && strcmp((char *) version, PG_XML_DEFAULT_VERSION) != 0)		|| (encoding && encoding != PG_UTF8)		|| standalone != -1)	{		appendStringInfoString(buf, "<?xml");		if (version)			appendStringInfo(buf, " version=\"%s\"", version);		else			appendStringInfo(buf, " version=\"%s\"", PG_XML_DEFAULT_VERSION);		if (encoding && encoding != PG_UTF8)		{			/*			 * XXX might be useful to convert this to IANA names (ISO-8859-1			 * instead of LATIN1 etc.); needs field experience			 */			appendStringInfo(buf, " encoding=\"%s\"",							 pg_encoding_to_char(encoding));		}		if (standalone == 1)			appendStringInfoString(buf, " standalone=\"yes\"");		else if (standalone == 0)			appendStringInfoString(buf, " standalone=\"no\"");		appendStringInfoString(buf, "?>");		return true;	}	else		return false;}/* * Convert a C string to XML internal representation * * TODO maybe, libxml2's xmlreader is better? (do not construct DOM, * yet do not use SAX - see xmlreader.c) */static xmlDocPtrxml_parse(text *data, XmlOptionType xmloption_arg, bool preserve_whitespace,		  xmlChar * encoding){	int32		len;	xmlChar    *string;	xmlChar    *utf8string;	xmlParserCtxtPtr ctxt;	xmlDocPtr	doc;	len = VARSIZE(data) - VARHDRSZ;		/* will be useful later */	string = xml_text2xmlChar(data);	utf8string = pg_do_encoding_conversion(string,										   len,										   encoding ?										   xmlChar_to_encoding(encoding) :										   GetDatabaseEncoding(),										   PG_UTF8);	xml_init();	xmlInitParser();	ctxt = xmlNewParserCtxt();	if (ctxt == NULL)		xml_ereport(ERROR, ERRCODE_OUT_OF_MEMORY,					"could not allocate parser context");	if (xmloption_arg == XMLOPTION_DOCUMENT)	{		/*		 * Note, that here we try to apply DTD defaults		 * (XML_PARSE_DTDATTR) according to SQL/XML:10.16.7.d: 'Default		 * values defined by internal DTD are applied'. As for external		 * DTDs, we try to support them too, (see SQL/XML:10.16.7.e)		 */		doc = xmlCtxtReadDoc(ctxt, utf8string,							 NULL,							 "UTF-8",							 XML_PARSE_NOENT | XML_PARSE_DTDATTR							 | (preserve_whitespace ? 0 : XML_PARSE_NOBLANKS));		if (doc == NULL)			xml_ereport(ERROR, ERRCODE_INVALID_XML_DOCUMENT,						"invalid XML document");	}	else	{		int			res_code;		size_t		count;		xmlChar    *version = NULL;		int			standalone = -1;		doc = xmlNewDoc(NULL);		res_code = parse_xml_decl(utf8string,								  &count, &version, NULL, &standalone);		if (res_code != 0)			xml_ereport_by_code(ERROR, ERRCODE_INVALID_XML_CONTENT,								"invalid XML content: invalid XML declaration",								res_code);		res_code = xmlParseBalancedChunkMemory(doc, NULL, NULL, 0,											   utf8string + count, NULL);		if (res_code != 0)			xml_ereport(ERROR, ERRCODE_INVALID_XML_CONTENT,						"invalid XML content");		doc->version = xmlStrdup(version);		doc->encoding = xmlStrdup((xmlChar *) "UTF-8");		doc->standalone = standalone;	}	xmlFreeParserCtxt(ctxt);	return doc;}/* * xmlChar<->text convertions */static xmlChar *xml_text2xmlChar(text *in){	int32		len = VARSIZE(in) - VARHDRSZ;	xmlChar    *res;	res = palloc(len + 1);	memcpy(res, VARDATA(in), len);	res[len] = '\0';	return (res);}/* * Manage the special context used for all libxml allocations */static voidxml_memory_init(void){	/*	 * Create memory context if not there already.  We make it a child of	 * TopMemoryContext, even though our current policy is that it doesn't	 * survive past transaction end, because we want to be really really	 * sure it doesn't go away before we've called xmlCleanupParser().	 */	if (LibxmlContext == NULL)		LibxmlContext = AllocSetContextCreate(TopMemoryContext,											  "LibxmlContext",											  ALLOCSET_DEFAULT_MINSIZE,											  ALLOCSET_DEFAULT_INITSIZE,											  ALLOCSET_DEFAULT_MAXSIZE);	/* Re-establish the callbacks even if already set */	xmlMemSetup(xml_pfree, xml_palloc, xml_repalloc, xml_pstrdup);}static voidxml_memory_cleanup(void){	if (LibxmlContext != NULL)	{		/* Give libxml a chance to clean up dangling pointers */		xmlCleanupParser();		/* And flush the context */		MemoryContextDelete(LibxmlContext);		LibxmlContext = NULL;	}}/* * Wrappers for memory management functions */static void *xml_palloc(size_t size){	return MemoryContextAlloc(LibxmlContext, size);}static void *xml_repalloc(void *ptr, size_t size){	return repalloc(ptr, size);}static voidxml_pfree(void *ptr){	pfree(ptr);}static char *xml_pstrdup(const char *string){	return MemoryContextStrdup(LibxmlContext, string);}/* * Wrapper for "ereport" function for XML-related errors.  The "msg" * is the SQL-level message; some can be adopted from the SQL/XML * standard.  This function adds libxml's native error messages, if * any, as detail. */static voidxml_ereport(int level, int sqlcode, const char *msg){	char	   *detail;	if (xml_err_buf->len > 0)	{		detail = pstrdup(xml_err_buf->data);		resetStringInfo(xml_err_buf);	}	else		detail = NULL;	/* libxml error messages end in '\n'; get rid of it */	if (detail)	{		size_t		len;		len = strlen(detail);		if (len > 0 && detail[len - 1] == '\n')			detail[len - 1] = '\0';		ereport(level,				(errcode(sqlcode),				 errmsg("%s", msg),				 errdetail("%s", detail)));	}	else	{		ereport(level,				(errcode(sqlcode),				 errmsg("%s", msg)));	}}/* * Error handler for libxml error messages */static voidxml_errorHandler(void *ctxt, const char *msg,...){	/* Append the formatted text to xml_err_buf */	for (;;)	{		va_list		args;		bool		success;		/* Try to format the data. */		va_start(args, msg);		success = appendStringInfoVA(xml_err_buf, msg, args);		va_end(args);		if (success)			break;		/* Double the buffer size and try again. */		enlargeStringInfo(xml_err_buf, xml_err_buf->maxlen);	}}/* * Wrapper for "ereport" function for XML-related errors.  The "msg" * is the SQL-level message; some can be adopted from the SQL/XML * standard.  This function uses "code" to create a textual detail * message.  At the moment, we only need to cover those codes that we * may raise in this file. */static voidxml_ereport_by_code(int level, int sqlcode,					const char *msg, int code){	const char *det;	switch (code)	{		case XML_ERR_INVALID_CHAR:			det = gettext_noop("Invalid character value.");			break;		case XML_ERR_SPACE_REQUIRED:			det = gettext_noop("Space required.");			break;		case XML_ERR_STANDALONE_VALUE:			det = gettext_noop("standalone accepts only 'yes' or 'no'.");			break;		case XML_ERR_VERSION_MISSING:			det = gettext_noop("Malformed declaration: missing version.");			break;		case XML_ERR_MISSING_ENCODING:			det = gettext_noop("Missing encoding in text declaration.");			break;		case XML_ERR_XMLDECL_NOT_FINISHED:			det = gettext_noop("Parsing XML declaration: '?>' expected.");			break;		default:			det = gettext_noop("Unrecognized libxml error code: %d.");			break;	}	ereport(level,			(errcode(sqlcode),			 errmsg("%s", msg),			 errdetail(det, code)));}/* * Convert one char in the current server encoding to a Unicode codepoint. */static pg_wcharsqlchar_to_unicode(char *s){	char	   *utf8string;	pg_wchar	ret[2];			/* need space for trailing zero */	utf8string = (char *) pg_do_encoding_conversion((unsigned char *) s,													pg_mblen(s),													GetDatabaseEncoding(),													PG_UTF8);	pg_encoding_mb2wchar_with_len(PG_UTF8, utf8string, ret, pg_mblen(s));	return ret[0];}static boolis_valid_xml_namefirst(pg_wchar c){	/* (Letter | '_' | ':') */	return (xmlIsBaseCharQ(c) || xmlIsIdeographicQ(c)			|| c == '_' || c == ':');}static boolis_valid_xml_namechar(pg_wchar c){	/* Letter | Digit | '.' | '-' | '_' | ':' | CombiningChar | Extender */	return (xmlIsBaseCharQ(c) || xmlIsIdeographicQ(c)			|| xmlIsDigitQ(c)			|| c == '.' || c == '-' || c == '_' || c == ':'			|| xmlIsCombiningQ(c)			|| xmlIsExtenderQ(c));}#endif   /* USE_LIBXML *//* * Map SQL identifier to XML name; see SQL/XML:2003 section 9.1. */char *map_sql_identifier_to_xml_name(char *ident, bool fully_escaped,							   bool escape_period){#ifdef USE_LIBXML	StringInfoData buf;	char	   *p;	/*	 * SQL/XML doesn't make use of this case anywhere, so it's probably a	 * mistake.	 */	Assert(fully_escaped || !escape_period);	initStringInfo(&buf);	for (p = ident; *p; p += pg_mblen(p))	{		if (*p == ':' && (p == ident || fully_escaped))			appendStringInfo(&buf, "_x003A_");		else if (*p == '_' && *(p + 1) == 'x')			appendStringInfo(&buf, "_x005F_");		else if (fully_escaped && p == ident &&				 pg_strncasecmp(p, "xml", 3) == 0)		{			if (*p == 'x')				appendStringInfo(&buf, "_x0078_");			else				appendStringInfo(&buf, "_x0058_");		}		else if (escape_period && *p == '.')			appendStringInfo(&buf, "_x002E_");		else		{			pg_wchar	u = sqlchar_to_unicode(p);			if ((p == ident)				? !is_valid_xml_namefirst(u)				: !is_valid_xml_namechar(u))				appendStringInfo(&buf, "_x%04X_", (unsigned int) u);			else				appendBinaryStringInfo(&buf, p, pg_mblen(p));		}	}	return buf.data;#else							/* not USE_LIBXML */	NO_XML_SUPPORT();	return NULL;#endif   /* not USE_LIBXML */}/* * Map a Unicode codepoint into the current server encoding. */static char *unicode_to_sqlchar(pg_wchar c){	static unsigned char utf8string[5]; /* need trailing zero */	if (c <= 0x7F)	{		utf8string[0] = c;	}	else if (c <= 0x7FF)	{		utf8string[0] = 0xC0 | ((c >> 6) & 0x1F);		utf8string[1] = 0x80 | (c & 0x3F);	}	else if (c <= 0xFFFF)	{		utf8string[0] = 0xE0 | ((c >> 12) & 0x0F);		utf8string[1] = 0x80 | ((c >> 6) & 0x3F);		utf8string[2] = 0x80 | (c & 0x3F);	}	else	{		utf8string[0] = 0xF0 | ((c >> 18) & 0x07);		utf8string[1] = 0x80 | ((c >> 12) & 0x3F);		utf8string[2] = 0x80 | ((c >> 6) & 0x3F);		utf8string[3] = 0x80 | (c & 0x3F);	}	return (char *) pg_do_encoding_conversion(utf8string,											  pg_mblen((char *) utf8string),											  PG_UTF8,											  GetDatabaseEncoding());}/* * Map XML name to SQL identifier; see SQL/XML:2003 section 9.17. */char *map_xml_name_to_sql_identifier(char *name){	StringInfoData buf;	char	   *p;	initStringInfo(&buf);	for (p = name; *p; p += pg_mblen(p))	{		if (*p == '_' && *(p + 1) == 'x'			&& isxdigit((unsigned char) *(p + 2))			&& isxdigit((unsigned char) *(p + 3))			&& isxdigit((unsigned char) *(p + 4))			&& isxdigit((unsigned char) *(p + 5))			&& *(p + 6) == '_')		{			unsigned int u;			sscanf(p + 2, "%X", &u);			appendStringInfoString(&buf, unicode_to_sqlchar(u));			p += 6;		}		else			appendBinaryStringInfo(&buf, p, pg_mblen(p));	}	return buf.data;}/* * Map SQL value to XML value; see SQL/XML:2003 section 9.16. */char *map_sql_value_to_xml_value(Datum value, Oid type){	StringInfoData buf;	initStringInfo(&buf);	if (type_is_array(type))	{		ArrayType  *array;		Oid			elmtype;		int16		elmlen;		bool		elmbyval;		char		elmalign;		int			num_elems;		Datum	   *elem_values;		bool	   *elem_nulls;		int			i;		array = DatumGetArrayTypeP(value);		elmtype = ARR_ELEMTYPE(array);		get_typlenbyvalalign(elmtype, &elmlen, &elmbyval, &elmalign);		deconstruct_array(array, elmtype,						  elmlen, elmbyval, elmalign,						  &elem_values, &elem_nulls,						  &num_elems);		for (i = 0; i < num_elems; i++)		{			if (elem_nulls[i])				continue;			appendStringInfoString(&buf, "<element>");			appendStringInfoString(&buf,								   map_sql_value_to_xml_value(elem_values[i],															  elmtype));			appendStringInfoString(&buf, "</element>");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -