/* * Initialize for xml parsing. */ void pgxml_parser_init(void) { /* Set up error handling (we share the core's error handler) */ pg_xml_init(); /* Initialize libxml */ xmlInitParser(); xmlSubstituteEntitiesDefault(1); xmlLoadExtDtdDefaultValue = 1; }
/* * Entry point for native XML support, shred XML document into tables and * create indexes for future XQuery support * @param * @return */ Datum build_xmlindex(PG_FUNCTION_ARGS) { xmltype *xmldata = NULL; char *xmldataint = NULL; text *xml_name = NULL; char *xml_nameint; int xmldatalen = -1; int loader_return = 0; // false int4 did; #ifdef USE_LIBXML elog(INFO, "build_xmlindex started"); xmldata = PG_GETARG_XML_P(0); xmldataint = VARDATA(xmldata); xmldatalen = VARSIZE(xmldata) - VARHDRSZ; xmldataint[xmldatalen] = 0; xml_name = PG_GETARG_TEXT_P(1); xml_nameint = VARDATA(xml_name); xml_nameint[VARSIZE(xml_name) - VARHDRSZ] = 0; //initialize LibXML structures, if allready done -> do nothing pg_xml_init(); xmlInitParser(); did = insert_xmldata_into_table(xmldataint, xml_nameint); loader_return = xml_index_entry(xmldataint, xmldatalen, did); elog(INFO, "build_xmlindex ended"); if (loader_return == XML_INDEX_LOADER_SUCCES) { PG_RETURN_BOOL(true); } else { PG_RETURN_BOOL(false); } #else NO_XML_SUPPORT(); PG_RETURN_BOOL (false); #endif }
/* * Initialize for xml parsing. * * As with the underlying pg_xml_init function, calls to this MUST be followed * by a PG_TRY block that guarantees that pg_xml_done is called. */ PgXmlErrorContext * pgxml_parser_init(PgXmlStrictness strictness) { PgXmlErrorContext *xmlerrcxt; /* Set up error handling (we share the core's error handler) */ xmlerrcxt = pg_xml_init(strictness); /* Note: we're assuming an elog cannot be thrown by the following calls */ /* Initialize libxml */ xmlInitParser(); xmlSubstituteEntitiesDefault(1); xmlLoadExtDtdDefaultValue = 1; return xmlerrcxt; }
/** * Validation function take first argument as XML type, then check if is * well formated. If so, do the same for DTD document. If both success, check * XML document against DTD schema restrictions. * @return true if pass, false otherwise */ Datum xmlvalidate_dtd(PG_FUNCTION_ARGS) { #ifdef USE_LIBXML int ret = -1; xmlValidCtxtPtr validctxt = NULL; xmlDtdPtr dtd = NULL; bool result = false; text *data = NULL; char *dtdstr = NULL; xmltype *xmldata = NULL; char *xmldataint = NULL; xmlChar *xmldatastr = NULL; int lenxml = -1; // length of xml data xmlDocPtr doc = NULL; // creating xmlChar * from internal xmltype of stored XML xmldata = PG_GETARG_XML_P(0); xmldataint = VARDATA(xmldata); lenxml = VARSIZE(xmldata) - VARHDRSZ; xmldatastr = (xmlChar *) palloc((lenxml + 1) * sizeof(xmlChar)); memcpy(xmldatastr, xmldataint, lenxml); xmldatastr[lenxml] = '\0'; // creating xmlChar* from text representation of DTD data = PG_GETARG_TEXT_P(1); dtdstr = text_to_cstring(data); //initialize LibXML structures, if allready done -> do nothing pg_xml_init(); xmlInitParser(); doc = xmlReadMemory((const char *)xmldatastr, lenxml, "include.xml", NULL, 0); if (doc == NULL) { elog(ERROR, "Failed to parse XML document"); PG_RETURN_BOOL (false); } // create DTD from memory, must use XML_CHAR_ENCODING_NONE dtd = xmlIOParseDTD(NULL, xmlParserInputBufferCreateMem(dtdstr, strlen(dtdstr), XML_CHAR_ENCODING_NONE), XML_CHAR_ENCODING_NONE); if (dtd == NULL) { // unable to create parser context elog(ERROR, "Error with creating DTD schema, check if schema is valid"); PG_RETURN_BOOL (false); } validctxt = xmlNewValidCtxt(); if (validctxt == NULL) { // cant create validation context elog(INFO ,"cant create validation context"); xmlFreeDtd(dtd); PG_RETURN_BOOL (false); } ret = xmlValidateDtd(validctxt, doc, dtd); if (ret == 0) { elog(INFO, "Validates"); result = true; } else if (ret > 0) { elog(INFO, "Dont validates"); result = false; } else { elog(INFO, "Validation generated an internal error"); result = false; } xmlFreeDtd(dtd); xmlFreeValidCtxt(validctxt); xmlFreeDoc(doc); // clean up document in memmory xmlCleanupParser(); // clean up stream parser PG_RETURN_BOOL (result); #else NO_XML_SUPPORT(); PG_RETURN_BOOL (false); #endif }
/** * Validation function take first argument as XML type, then check if is * well formated. If so, do the same for RNG document. If both success, check * XML document against RNG schema restrictions. * @return true if pass, false otherwise */ Datum xmlvalidate_rng(PG_FUNCTION_ARGS) { #ifdef USE_LIBXML text *data = NULL; char *rng = NULL; xmlChar *utf8rng = NULL; xmltype *xmldata = NULL; char *xmldataint = NULL; xmlChar *xmldatastr = NULL; bool result = false; int lenxml = -1; // length of xml data int lenrng = -1; // length of xsd data xmlDocPtr doc = NULL; int ret = -1; xmlRelaxNGParserCtxtPtr ctxt = NULL; xmlRelaxNGPtr schema = NULL; xmlRelaxNGValidCtxtPtr validctxt = NULL; // creating xmlChar * from internal xmltype of stored XML xmldata = PG_GETARG_XML_P(0); xmldataint = VARDATA(xmldata); lenxml = VARSIZE(xmldata) - VARHDRSZ; xmldatastr = (xmlChar *) palloc((lenxml + 1) * sizeof(xmlChar)); memcpy(xmldatastr, xmldataint, lenxml); xmldatastr[lenxml] = '\0'; // creating xmlChar* from text representation of XSD data = PG_GETARG_TEXT_P(1); lenrng = VARSIZE(data) - VARHDRSZ; rng = text_to_cstring(data); //encode XML to internal representation with UTF-8, only one used in LibXML utf8rng = pg_do_encoding_conversion((unsigned char*)rng, lenrng, GetDatabaseEncoding(), PG_UTF8); //initialize LibXML structures, if allready done -> do nothing pg_xml_init(); xmlInitParser(); doc = xmlReadMemory((const char *)xmldatastr, lenxml, "include.xml", NULL, 0); if (doc == NULL) { elog(ERROR, "Failed to parse XML document"); PG_RETURN_BOOL (false); } ctxt = xmlRelaxNGNewMemParserCtxt(rng, lenrng); if (ctxt == NULL) { // unable to create parser context elog(ERROR, "Error with creating schema, check if RelaxNG schema is valid"); PG_RETURN_BOOL (false); } schema = xmlRelaxNGParse(ctxt); // parse schema xmlRelaxNGFreeParserCtxt(ctxt); // realease parser context validctxt = xmlRelaxNGNewValidCtxt(schema); if (validctxt == NULL) { // cant create validation context xmlRelaxNGFree(schema); elog(ERROR, "Cant create validation context"); PG_RETURN_BOOL (false); } // set errors to SQL errors xmlRelaxNGSetValidErrors(validctxt, xml_error_handler, NULL, 0); ret = xmlRelaxNGValidateDoc(validctxt, doc); if (ret == 0) { elog(INFO, "Validates"); result = true; } else if (ret > 0) { elog(INFO, "Dont validates"); result = false; } else { elog(INFO, "Validation generated an internal error"); result = false; } xmlRelaxNGFree(schema); xmlRelaxNGFreeValidCtxt(validctxt); xmlFreeDoc(doc); // clean up document in memmory xmlCleanupParser(); // clean up stream parser PG_RETURN_BOOL (result); #else NO_XML_SUPPORT(); PG_RETURN_BOOL (false); #endif }