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

📄 xml.c

📁 postgresql8.3.4源码,开源数据库
💻 C
📖 第 1 页 / 共 5 页
字号:
Datumxmltotext(PG_FUNCTION_ARGS){	xmltype    *data = PG_GETARG_XML_P(0);	/* It's actually binary compatible. */	PG_RETURN_TEXT_P((text *) data);}text *xmltotext_with_xmloption(xmltype *data, XmlOptionType xmloption_arg){	if (xmloption_arg == XMLOPTION_DOCUMENT && !xml_is_document(data))		ereport(ERROR,				(errcode(ERRCODE_NOT_AN_XML_DOCUMENT),				 errmsg("not an XML document")));	/* It's actually binary compatible, save for the above check. */	return (text *) data;}xmltype *xmlelement(XmlExprState *xmlExpr, ExprContext *econtext){#ifdef USE_LIBXML	XmlExpr    *xexpr = (XmlExpr *) xmlExpr->xprstate.expr;	xmltype    *result;	List	   *named_arg_strings;	List	   *arg_strings;	int			i;	ListCell   *arg;	ListCell   *narg;	xmlBufferPtr buf;	xmlTextWriterPtr writer;	/*	 * We first evaluate all the arguments, then start up libxml and create	 * the result.	This avoids issues if one of the arguments involves a call	 * to some other function or subsystem that wants to use libxml on its own	 * terms.	 */	named_arg_strings = NIL;	i = 0;	foreach(arg, xmlExpr->named_args)	{		ExprState  *e = (ExprState *) lfirst(arg);		Datum		value;		bool		isnull;		char	   *str;		value = ExecEvalExpr(e, econtext, &isnull, NULL);		if (isnull)			str = NULL;		else			str = OutputFunctionCall(&xmlExpr->named_outfuncs[i], value);		named_arg_strings = lappend(named_arg_strings, str);		i++;	}	arg_strings = NIL;	foreach(arg, xmlExpr->args)	{		ExprState  *e = (ExprState *) lfirst(arg);		Datum		value;		bool		isnull;		char	   *str;		value = ExecEvalExpr(e, econtext, &isnull, NULL);		/* here we can just forget NULL elements immediately */		if (!isnull)		{			str = map_sql_value_to_xml_value(value,											 exprType((Node *) e->expr));			arg_strings = lappend(arg_strings, str);		}	}	/* now safe to run libxml */	xml_init();	buf = xmlBufferCreate();	writer = xmlNewTextWriterMemory(buf, 0);	xmlTextWriterStartElement(writer, (xmlChar *) xexpr->name);	forboth(arg, named_arg_strings, narg, xexpr->arg_names)	{		char	   *str = (char *) lfirst(arg);		char	   *argname = strVal(lfirst(narg));		if (str)		{			xmlTextWriterWriteAttribute(writer,										(xmlChar *) argname,										(xmlChar *) str);			pfree(str);		}	}	foreach(arg, arg_strings)	{		char	   *str = (char *) lfirst(arg);		xmlTextWriterWriteRaw(writer, (xmlChar *) 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, XmlOptionType xmloption_arg, bool preserve_whitespace){#ifdef USE_LIBXML	xmlDocPtr	doc;	doc = xml_parse(data, xmloption_arg, preserve_whitespace, NULL);	xmlFreeDoc(doc);	return (xmltype *) data;#else	NO_XML_SUPPORT();	return NULL;#endif}xmltype *xmlpi(char *target, text *arg, bool arg_is_null, bool *result_is_null){#ifdef USE_LIBXML	xmltype    *result;	StringInfoData buf;	if (pg_strcasecmp(target, "xml") == 0)		ereport(ERROR,				(errcode(ERRCODE_SYNTAX_ERROR), /* really */				 errmsg("invalid XML processing instruction"),				 errdetail("XML processing instruction target name cannot be \"%s\".", target)));	/*	 * Following the SQL standard, the null check comes after the syntax check	 * above.	 */	*result_is_null = arg_is_null;	if (*result_is_null)		return NULL;	initStringInfo(&buf);	appendStringInfo(&buf, "<?%s", target);	if (arg != NULL)	{		char	   *string;		string = _textout(arg);		if (strstr(string, "?>") != NULL)			ereport(ERROR,					(errcode(ERRCODE_INVALID_XML_PROCESSING_INSTRUCTION),					 errmsg("invalid XML processing instruction"),			errdetail("XML processing instruction cannot contain \"?>\".")));		appendStringInfoChar(&buf, ' ');		appendStringInfoString(&buf, string + strspn(string, " "));		pfree(string);	}	appendStringInfoString(&buf, "?>");	result = stringinfo_to_xmltype(&buf);	pfree(buf.data);	return result;#else	NO_XML_SUPPORT();	return NULL;#endif}xmltype *xmlroot(xmltype *data, text *version, int standalone){#ifdef USE_LIBXML	char	   *str;	size_t		len;	xmlChar    *orig_version;	int			orig_standalone;	StringInfoData buf;	len = VARSIZE(data) - VARHDRSZ;	str = palloc(len + 1);	memcpy(str, VARDATA(data), len);	str[len] = '\0';	parse_xml_decl((xmlChar *) str, &len, &orig_version, NULL, &orig_standalone);	if (version)		orig_version = xml_text2xmlChar(version);	else		orig_version = NULL;	switch (standalone)	{		case XML_STANDALONE_YES:			orig_standalone = 1;			break;		case XML_STANDALONE_NO:			orig_standalone = 0;			break;		case XML_STANDALONE_NO_VALUE:			orig_standalone = -1;			break;		case XML_STANDALONE_OMITTED:			/* leave original value */			break;	}	initStringInfo(&buf);	print_xml_decl(&buf, orig_version, 0, orig_standalone);	appendStringInfoString(&buf, str + len);	return stringinfo_to_xmltype(&buf);#else	NO_XML_SUPPORT();	return NULL;#endif}/* * Validate document (given as string) against DTD (given as external link) * * This has been removed because it is a security hole: unprivileged users * should not be able to use Postgres to fetch arbitrary external files, * which unfortunately is exactly what libxml is willing to do with the DTD * parameter. */Datumxmlvalidate(PG_FUNCTION_ARGS){	ereport(ERROR,			(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),			 errmsg("xmlvalidate is not implemented")));	return 0;}boolxml_is_document(xmltype *arg){#ifdef USE_LIBXML	bool		result;	xmlDocPtr	doc = NULL;	MemoryContext ccxt = CurrentMemoryContext;	PG_TRY();	{		doc = xml_parse((text *) arg, XMLOPTION_DOCUMENT, true, NULL);		result = true;	}	PG_CATCH();	{		ErrorData  *errdata;		MemoryContext ecxt;		ecxt = MemoryContextSwitchTo(ccxt);		errdata = CopyErrorData();		if (errdata->sqlerrcode == ERRCODE_INVALID_XML_DOCUMENT)		{			FlushErrorState();			result = false;		}		else		{			MemoryContextSwitchTo(ecxt);			PG_RE_THROW();		}	}	PG_END_TRY();	if (doc)		xmlFreeDoc(doc);	return result;#else							/* not USE_LIBXML */	NO_XML_SUPPORT();	return false;#endif   /* not USE_LIBXML */}/* * xml cleanup function for transaction end.  This is also called on * subtransaction abort; see notes at top of file for rationale. */voidAtEOXact_xml(void){#ifdef USE_LIBXML	xml_memory_cleanup();#endif}#ifdef USE_LIBXML/* * Set up for use of libxml --- this should be called by each function that * is about to use libxml facilities. * * TODO: xmlChar is utf8-char, make proper tuning (initdb with enc!=utf8 and * check) */static voidxml_init(void){	static bool first_time = true;	if (first_time)	{		/* Stuff we need do only once per session */		MemoryContext oldcontext;		/*		 * Currently, we have no pure UTF-8 support for internals -- check if		 * we can work.		 */		if (sizeof(char) != sizeof(xmlChar))			ereport(ERROR,					(errmsg("could not initialize XML library"),					 errdetail("libxml2 has incompatible char type: sizeof(char)=%u, sizeof(xmlChar)=%u.",							   (int) sizeof(char), (int) sizeof(xmlChar))));		/* create error buffer in permanent context */		oldcontext = MemoryContextSwitchTo(TopMemoryContext);		xml_err_buf = makeStringInfo();		MemoryContextSwitchTo(oldcontext);		/* Now that xml_err_buf exists, safe to call xml_errorHandler */		xmlSetGenericErrorFunc(NULL, xml_errorHandler);		/* Set up memory allocation our way, too */		xml_memory_init();		/* Check library compatibility */		LIBXML_TEST_VERSION;		first_time = false;	}	else	{		/* Reset pre-existing buffer to empty */		Assert(xml_err_buf != NULL);		resetStringInfo(xml_err_buf);		/*		 * We re-establish the callback functions every time.  This makes it		 * safe for other subsystems (PL/Perl, say) to also use libxml with		 * their own callbacks ... so long as they likewise set up the		 * callbacks on every use.	It's cheap enough to not be worth worrying		 * about, anyway.		 */		xmlSetGenericErrorFunc(NULL, xml_errorHandler);		xml_memory_init();	}}/* * SQL/XML allows storing "XML documents" or "XML content".  "XML * documents" are specified by the XML specification and are parsed * easily by libxml.  "XML content" is specified by SQL/XML as the * production "XMLDecl? content".  But libxml can only parse the * "content" part, so we have to parse the XML declaration ourselves * to complete this. */#define CHECK_XML_SPACE(p) \	do { \		if (!xmlIsBlank_ch(*(p))) \			return XML_ERR_SPACE_REQUIRED; \	} while (0)#define SKIP_XML_SPACE(p) \	while (xmlIsBlank_ch(*(p))) (p)++/* Letter | Digit | '.' | '-' | '_' | ':' | CombiningChar | Extender *//* Beware of multiple evaluations of argument! */#define PG_XMLISNAMECHAR(c) \	(xmlIsBaseChar_ch(c) || xmlIsIdeographicQ(c) \			|| xmlIsDigit_ch(c) \			|| c == '.' || c == '-' || c == '_' || c == ':' \			|| xmlIsCombiningQ(c) \			|| xmlIsExtender_ch(c))static intparse_xml_decl(const xmlChar * str, size_t *lenp,			   xmlChar ** version, xmlChar ** encoding, int *standalone){	const xmlChar *p;	const xmlChar *save_p;	size_t		len;	int			utf8char;	int			utf8len;	xml_init();	if (version)		*version = NULL;	if (encoding)		*encoding = NULL;	if (standalone)		*standalone = -1;	p = str;	if (xmlStrncmp(p, (xmlChar *) "<?xml", 5) != 0)		goto finished;	/* if next char is name char, it's a PI like <?xml-stylesheet ...?> */	utf8len = strlen((const char *) (p + 5));	utf8char = xmlGetUTF8Char(p + 5, &utf8len);	if (PG_XMLISNAMECHAR(utf8char))		goto finished;	p += 5;	/* version */	CHECK_XML_SPACE(p);	SKIP_XML_SPACE(p);	if (xmlStrncmp(p, (xmlChar *) "version", 7) != 0)		return XML_ERR_VERSION_MISSING;	p += 7;	SKIP_XML_SPACE(p);	if (*p != '=')		return XML_ERR_VERSION_MISSING;	p += 1;	SKIP_XML_SPACE(p);	if (*p == '\'' || *p == '"')	{		const xmlChar *q;		q = xmlStrchr(p + 1, *p);		if (!q)			return XML_ERR_VERSION_MISSING;		if (version)			*version = xmlStrndup(p + 1, q - p - 1);		p = q + 1;	}	else		return XML_ERR_VERSION_MISSING;	/* encoding */	save_p = p;	SKIP_XML_SPACE(p);	if (xmlStrncmp(p, (xmlChar *) "encoding", 8) == 0)	{		CHECK_XML_SPACE(save_p);		p += 8;		SKIP_XML_SPACE(p);		if (*p != '=')			return XML_ERR_MISSING_ENCODING;		p += 1;		SKIP_XML_SPACE(p);		if (*p == '\'' || *p == '"')		{			const xmlChar *q;			q = xmlStrchr(p + 1, *p);			if (!q)				return XML_ERR_MISSING_ENCODING;			if (encoding)				*encoding = xmlStrndup(p + 1, q - p - 1);			p = q + 1;		}		else			return XML_ERR_MISSING_ENCODING;	}	else	{		p = save_p;	}	/* standalone */	save_p = p;	SKIP_XML_SPACE(p);	if (xmlStrncmp(p, (xmlChar *) "standalone", 10) == 0)	{		CHECK_XML_SPACE(save_p);		p += 10;		SKIP_XML_SPACE(p);		if (*p != '=')			return XML_ERR_STANDALONE_VALUE;		p += 1;		SKIP_XML_SPACE(p);		if (xmlStrncmp(p, (xmlChar *) "'yes'", 5) == 0 ||			xmlStrncmp(p, (xmlChar *) "\"yes\"", 5) == 0)		{			*standalone = 1;			p += 5;		}		else if (xmlStrncmp(p, (xmlChar *) "'no'", 4) == 0 ||				 xmlStrncmp(p, (xmlChar *) "\"no\"", 4) == 0)		{			*standalone = 0;			p += 4;		}		else			return XML_ERR_STANDALONE_VALUE;	}	else	{		p = save_p;	}	SKIP_XML_SPACE(p);	if (xmlStrncmp(p, (xmlChar *) "?>", 2) != 0)		return XML_ERR_XMLDECL_NOT_FINISHED;	p += 2;finished:	len = p - str;	for (p = str; p < str + len; p++)		if (*p > 127)			return XML_ERR_INVALID_CHAR;	if (lenp)		*lenp = len;

⌨️ 快捷键说明

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