/* $Id$ * * This is free software, you may use it and distribute it under the same terms as * Perl itself. * * Copyright 2001-2003 AxKit.com Ltd., 2002-2006 Christian Glahn, 2006-2009 Petr Pajas */ #ifdef __cplusplus extern "C" { #endif #if defined(_MSC_VER) #define _CRT_SECURE_NO_DEPRECATE 1 #define _CRT_NONSTDC_NO_DEPRECATE 1 #endif /* perl stuff */ #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #define NEED_newRV_noinc_GLOBAL #define NEED_sv_2pv_flags #include "ppport.h" #include "Av_CharPtrPtr.h" /* XS_*_charPtrPtr() */ #include #ifndef WIN32 #include #endif /* libxml2 configuration properties */ #include #define DEBUG_C14N /* libxml2 stuff */ #include #include #include #include #include #include #include #include #include #include #include #include /* #include */ #include #include #include #ifdef LIBXML_PATTERN_ENABLED #include #endif #ifdef LIBXML_REGEXP_ENABLED #include #endif #if LIBXML_VERSION >= 20510 #define HAVE_SCHEMAS #include #include #endif #if LIBXML_VERSION >= 20621 #define WITH_SERRORS #ifdef LIBXML_READER_ENABLED #define HAVE_READER_SUPPORT #include #endif #endif #ifdef LIBXML_CATALOG_ENABLED #include #endif #ifdef HAVE_READER_SUPPORT typedef enum { XML_TEXTREADER_NONE = -1, XML_TEXTREADER_START= 0, XML_TEXTREADER_ELEMENT= 1, XML_TEXTREADER_END= 2, XML_TEXTREADER_EMPTY= 3, XML_TEXTREADER_BACKTRACK= 4, XML_TEXTREADER_DONE= 5, XML_TEXTREADER_ERROR= 6 } xmlTextReaderState; typedef enum { XML_TEXTREADER_NOT_VALIDATE = 0, XML_TEXTREADER_VALIDATE_DTD = 1, XML_TEXTREADER_VALIDATE_RNG = 2, XML_TEXTREADER_VALIDATE_XSD = 4 } xmlTextReaderValidate; #endif /* HAVE_READER_SUPPORT */ /* GDOME support * libgdome installs only the core functions to the system. * this is not enough for XML::LibXML <-> XML::GDOME conversion. * therefore there is the need to ship as well the GDOME core headers. */ #ifdef XML_LIBXML_GDOME_SUPPORT #include #include #endif #if LIBXML_VERSION < 20621 /* HTML_PARSE_RECOVER was added in libxml2 2.6.21 */ # define HTML_PARSE_RECOVER XML_PARSE_RECOVER #endif /* XML::LibXML stuff */ #include "perl-libxml-mm.h" #include "perl-libxml-sax.h" #include "dom.h" #include "xpath.h" #include "xpathcontext.h" #ifdef __cplusplus } #endif #define TEST_PERL_FLAG(flag) \ SvTRUE(get_sv(flag, FALSE)) ? 1 : 0 #ifdef HAVE_READER_SUPPORT #define LIBXML_READER_TEST_ELEMENT(reader,name,nsURI) \ (xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) && \ ((!nsURI && !name) \ || \ (!nsURI && xmlStrcmp((const xmlChar*)name, xmlTextReaderConstName(reader) ) == 0 ) \ || \ (nsURI && xmlStrcmp((const xmlChar*)nsURI, xmlTextReaderConstNamespaceUri(reader))==0 \ && \ (!name || xmlStrcmp((const xmlChar*)name, xmlTextReaderConstLocalName(reader)) == 0))) #endif /* this should keep the default */ static xmlExternalEntityLoader LibXML_old_ext_ent_loader = NULL; /* global external entity loader */ SV *EXTERNAL_ENTITY_LOADER_FUNC = (SV *)NULL; SV* PROXY_NODE_REGISTRY_MUTEX = NULL; /* **************************************************************** * Error handler * **************************************************************** */ #ifdef WITH_SERRORS #define INIT_READER_ERROR_HANDLER(reader) #define PREINIT_SAVED_ERROR SV* saved_error = sv_2mortal(newSV(0)); #define INIT_ERROR_HANDLER \ xmlSetGenericErrorFunc((void *)saved_error, \ (xmlGenericErrorFunc) LibXML_flat_handler); \ xmlSetStructuredErrorFunc((void *)saved_error, \ (xmlStructuredErrorFunc)LibXML_struct_error_handler) #define REPORT_ERROR(recover) LibXML_report_error_ctx(saved_error, recover) #define CLEANUP_ERROR_HANDLER xmlSetGenericErrorFunc(NULL,NULL); \ xmlSetStructuredErrorFunc(NULL,NULL) #else /* WITH_SERRORS */ #define INIT_READER_ERROR_HANDLER(reader) \ if (reader) \ xmlTextReaderSetErrorHandler(reader, LibXML_reader_error_handler, \ sv_2mortal(newSVpv("",0))); #define PREINIT_SAVED_ERROR SV* saved_error = sv_2mortal(newSVpv("",0)); #define INIT_ERROR_HANDLER \ xmlSetGenericErrorFunc((void *) saved_error, \ (xmlGenericErrorFunc) LibXML_error_handler_ctx) #define REPORT_ERROR(recover) LibXML_report_error_ctx(saved_error, recover) #define CLEANUP_ERROR_HANDLER xmlSetGenericErrorFunc(NULL,NULL); #endif /* WITH_SERRORS */ #ifdef WITH_SERRORS void LibXML_struct_error_callback(SV * saved_error, SV * libErr ) { dTHX; dSP; if ( saved_error == NULL ) { warn( "have no save_error\n" ); } ENTER; SAVETMPS; PUSHMARK(SP); XPUSHs(sv_2mortal(libErr)); if ( saved_error != NULL && SvOK(saved_error) ) { XPUSHs(saved_error); } PUTBACK; if ( saved_error != NULL ) { call_pv( "XML::LibXML::Error::_callback_error", G_SCALAR | G_EVAL ); } else { call_pv( "XML::LibXML::Error::_instant_error_callback", G_SCALAR ); } SPAGAIN; if ( SvTRUE(ERRSV) ) { (void) POPs; croak_obj; } else { sv_setsv(saved_error, POPs); } PUTBACK; FREETMPS; LEAVE; } void LibXML_struct_error_handler(SV * saved_error, xmlErrorPtr error ) { const char * CLASS = "XML::LibXML::LibError"; SV* libErr; libErr = NEWSV(0,0); sv_setref_pv( libErr, CLASS, (void*)error ); LibXML_struct_error_callback( saved_error, libErr); } void LibXML_flat_handler(SV * saved_error, const char * msg, ...) { SV* sv; va_list args; sv = newSVpv("",0); va_start(args, msg); sv_vcatpvf(sv, msg, &args); va_end(args); xs_warn("flat error\n"); LibXML_struct_error_callback( saved_error, sv); } #endif /* WITH_SERRORS */ /* If threads-support is working correctly in libxml2 then * this method will be called with the correct thread-context */ void LibXML_error_handler_ctx(void * ctxt, const char * msg, ...) { va_list args; SV * saved_error = (SV *) ctxt; /* If saved_error is null we croak with the error */ if( NULL == saved_error ) { SV * sv = sv_2mortal(newSV(0)); va_start(args, msg); /* vfprintf(stderr, msg, args); */ sv_vsetpvfn(sv, msg, strlen(msg), &args, NULL, 0, NULL); va_end(args); croak("%s", SvPV_nolen(sv)); /* Otherwise, save the error */ } else { va_start(args, msg); /* vfprintf(stderr, msg, args); */ sv_vcatpvfn(saved_error, msg, strlen(msg), &args, NULL, 0, NULL); va_end(args); } } static void LibXML_validity_error_ctx(void * ctxt, const char *msg, ...) { va_list args; SV * saved_error = (SV *) ctxt; /* If saved_error is null we croak with the error */ if( NULL == saved_error ) { SV * sv = sv_2mortal(newSV(0)); va_start(args, msg); sv_vsetpvfn(sv, msg, strlen(msg), &args, NULL, 0, NULL); va_end(args); croak("%s", SvPV_nolen(sv)); /* Otherwise, save the error */ } else { va_start(args, msg); sv_vcatpvfn(saved_error, msg, strlen(msg), &args, NULL, 0, NULL); va_end(args); } } static void LibXML_validity_warning_ctx(void * ctxt, const char *msg, ...) { va_list args; SV * saved_error = (SV *) ctxt; STRLEN len; /* If saved_error is null we croak with the error */ if( NULL == saved_error ) { SV * sv = sv_2mortal(newSV(0)); va_start(args, msg); sv_vsetpvfn(sv, msg, strlen(msg), &args, NULL, 0, NULL); va_end(args); croak("LibXML_validity_warning_ctx internal error: context was null (%s)", SvPV_nolen(sv)); /* Otherwise, give the warning */ } else { va_start(args, msg); sv_vcatpvfn(saved_error, msg, strlen(msg), &args, NULL, 0, NULL); va_end(args); warn("validation error: %s", SvPV(saved_error, len)); } } static int LibXML_will_die_ctx(SV * saved_error, int recover) { #ifdef WITH_SERRORS if( saved_error!=NULL && SvOK(saved_error) ) { if ( recover == 0 ) { return 1; } } #else if( 0 < SvCUR( saved_error ) ) { if ( recover == 0 ) { return 1; } } #endif return 0; } static void LibXML_report_error_ctx(SV * saved_error, int recover) { #ifdef WITH_SERRORS if( saved_error!=NULL && SvOK( saved_error ) ) { if (!recover || recover==1) { dTHX; dSP; ENTER; SAVETMPS; PUSHMARK(SP); EXTEND(SP, 1); PUSHs(saved_error); PUTBACK; if (recover==1) { call_pv( "XML::LibXML::Error::_report_warning", G_SCALAR | G_DISCARD); } else { call_pv( "XML::LibXML::Error::_report_error", G_SCALAR | G_DISCARD); } SPAGAIN; PUTBACK; FREETMPS; LEAVE; } } #else if( 0 < SvCUR( saved_error ) ) { if( recover ) { if ( recover == 1 ) { warn("%s", SvPV_nolen(saved_error)); } /* else recover silently */ } else { croak("%s", SvPV_nolen(saved_error)); } } #endif } #ifdef HAVE_READER_SUPPORT #ifndef WITH_SERRORS static void LibXML_reader_error_handler(void * ctxt, const char * msg, xmlParserSeverities severity, xmlTextReaderLocatorPtr locator) { int line = xmlTextReaderLocatorLineNumber(locator); xmlChar * filename = xmlTextReaderLocatorBaseURI(locator); SV * msg_sv = sv_2mortal(C2Sv((xmlChar*) msg,NULL)); SV * error = sv_2mortal(newSVpv("", 0)); switch (severity) { case XML_PARSER_SEVERITY_VALIDITY_WARNING: sv_catpv(error, "Validity WARNING"); break; case XML_PARSER_SEVERITY_WARNING: sv_catpv(error, "Reader WARNING"); break; case XML_PARSER_SEVERITY_VALIDITY_ERROR: sv_catpv(error, "Validity ERROR"); break; case XML_PARSER_SEVERITY_ERROR: sv_catpv(error, "Reader ERROR"); break; } if (filename) { sv_catpvf(error, " in %s", filename); xmlFree(filename); } if (line >= 0) { sv_catpvf(error, " at line %d", line); } sv_catpvf(error, ": %s", SvPV_nolen(msg_sv)); if (severity == XML_PARSER_SEVERITY_VALIDITY_WARNING || severity == XML_PARSER_SEVERITY_WARNING ) { warn("%s", SvPV_nolen(error)); } else { SV * error_sv = (SV*) ctxt; if (error_sv) { sv_catpvf(error_sv, "%s ", SvPV_nolen(error)); } else { croak("%s",SvPV_nolen(error)); } } } #endif /* !defined WITH_SERRORS */ SV * LibXML_get_reader_error_data(xmlTextReaderPtr reader) { SV * saved_error = NULL; xmlTextReaderErrorFunc f = NULL; xmlTextReaderGetErrorHandler(reader, &f, (void **) &saved_error); return saved_error; } #ifndef WITH_SERRORS static void LibXML_report_reader_error(xmlTextReaderPtr reader) { SV * saved_error = NULL; xmlTextReaderErrorFunc f = NULL; xmlTextReaderGetErrorHandler(reader, &f, (void **) &saved_error); if ( saved_error && SvOK( saved_error) && 0 < SvCUR( saved_error ) ) { croak("%s", SvPV_nolen(saved_error)); } } #endif /* !defined WITH_SERRORS */ #endif /* HAVE_READER_SUPPORT */ static int LibXML_get_recover(HV * real_obj) { SV** item = hv_fetch( real_obj, "XML_LIBXML_RECOVER", 18, 0 ); return ( item != NULL && SvTRUE(*item) ) ? SvIV(*item) : 0; } static SV * LibXML_NodeToSv(HV * real_obj, xmlNodePtr real_doc) { SV** item = hv_fetch( real_obj, "XML_LIBXML_GDOME", 16, 0 ); if ( item != NULL && SvTRUE(*item) ) { return PmmNodeToGdomeSv(real_doc); } else { return PmmNodeToSv(real_doc, NULL); } } /* **************************************************************** * IO callbacks * **************************************************************** */ int LibXML_read_perl (SV * ioref, char * buffer, int len) { dTHX; dSP; int cnt; SV * read_results; IV read_results_iv; STRLEN read_length; char * chars; SV * tbuff = NEWSV(0,len); SV * tsize = newSViv(len); ENTER; SAVETMPS; PUSHMARK(SP); EXTEND(SP, 3); PUSHs(ioref); PUSHs(sv_2mortal(tbuff)); PUSHs(sv_2mortal(tsize)); PUTBACK; if (sv_isobject(ioref)) { cnt = call_method("read", G_SCALAR | G_EVAL); } else { cnt = call_pv("XML::LibXML::__read", G_SCALAR | G_EVAL); } SPAGAIN; if (cnt != 1) { croak("read method call failed"); } if (SvTRUE(ERRSV)) { (void) POPs; croak_obj; } read_results = POPs; if (!SvOK(read_results)) { croak("read error"); } read_results_iv = SvIV(read_results); chars = SvPV(tbuff, read_length); /* * If the file handle uses an encoding layer, the length parameter is * interpreted as character count, not as byte count. So it's possible * that more than len bytes are read which would overflow the buffer. * Check for this condition also by comparing the return value. */ if (read_results_iv != read_length || read_length > len) { croak("Read more bytes than requested. Do you use an encoding-related" " PerlIO layer?"); } strncpy(buffer, chars, read_length); PUTBACK; FREETMPS; LEAVE; return read_length; } /* used only by Reader */ int LibXML_close_perl (SV * ioref) { SvREFCNT_dec(ioref); return 0; } int LibXML_input_match(char const * filename) { int results; int count; SV * res; results = 0; { dTHX; dSP; ENTER; SAVETMPS; PUSHMARK(SP); EXTEND(SP, 1); PUSHs(sv_2mortal(newSVpv((char*)filename, 0))); PUTBACK; count = call_pv("XML::LibXML::InputCallback::_callback_match", G_SCALAR | G_EVAL); SPAGAIN; if (count != 1) { croak("match callback must return a single value"); } if (SvTRUE(ERRSV)) { (void) POPs; croak_obj; } res = POPs; if (SvTRUE(res)) { results = 1; } PUTBACK; FREETMPS; LEAVE; } return results; } void * LibXML_input_open(char const * filename) { SV * results; int count; dTHX; dSP; ENTER; SAVETMPS; PUSHMARK(SP); EXTEND(SP, 1); PUSHs(sv_2mortal(newSVpv((char*)filename, 0))); PUTBACK; count = call_pv("XML::LibXML::InputCallback::_callback_open", G_SCALAR | G_EVAL); SPAGAIN; if (count != 1) { croak("open callback must return a single value"); } if (SvTRUE(ERRSV)) { (void) POPs; croak_obj; } results = POPs; (void)SvREFCNT_inc(results); PUTBACK; FREETMPS; LEAVE; return (void *)results; } int LibXML_input_read(void * context, char * buffer, int len) { STRLEN res_len; const char * output; SV * ctxt; SV * output_sv; res_len = 0; ctxt = (SV *)context; { int count; dTHX; dSP; ENTER; SAVETMPS; PUSHMARK(SP); EXTEND(SP, 2); PUSHs(ctxt); PUSHs(sv_2mortal(newSViv(len))); PUTBACK; count = call_pv("XML::LibXML::InputCallback::_callback_read", G_SCALAR | G_EVAL); SPAGAIN; if (count != 1) { croak("read callback must return a single value"); } if (SvTRUE(ERRSV)) { (void) POPs; croak_obj; } /* * Handle undef()s gracefully, to avoid using POPpx which warns upon $^W * being set. See t/49callbacks_returning_undef.t and: * https://rt.cpan.org/Ticket/Display.html?id=70321 * */ output_sv = POPs; output = SvOK(output_sv) ? SvPV_nolen(output_sv) : NULL; if (output != NULL) { res_len = strlen(output); if (res_len) { strncpy(buffer, output, res_len); } else { buffer[0] = 0; } } PUTBACK; FREETMPS; LEAVE; } return res_len; } void LibXML_input_close(void * context) { SV * ctxt; ctxt = (SV *)context; { dTHX; dSP; ENTER; SAVETMPS; PUSHMARK(SP); EXTEND(SP, 1); PUSHs(ctxt); PUTBACK; call_pv("XML::LibXML::InputCallback::_callback_close", G_SCALAR | G_EVAL | G_DISCARD); SvREFCNT_dec(ctxt); if (SvTRUE(ERRSV)) { croak_obj; } FREETMPS; LEAVE; } } int LibXML_output_write_handler(void * ioref, char * buffer, int len) { if ( buffer != NULL && len > 0) { dTHX; dSP; SV * tbuff = newSVpv(buffer,len); SV * tsize = newSViv(len); ENTER; SAVETMPS; PUSHMARK(SP); EXTEND(SP, 3); PUSHs((SV*)ioref); PUSHs(sv_2mortal(tbuff)); PUSHs(sv_2mortal(tsize)); PUTBACK; call_pv("XML::LibXML::__write", G_SCALAR | G_EVAL | G_DISCARD ); if (SvTRUE(ERRSV)) { croak_obj; } FREETMPS; LEAVE; } return len; } int LibXML_output_close_handler( void * handler ) { return 1; } xmlParserInputPtr LibXML_load_external_entity( const char * URL, const char * ID, xmlParserCtxtPtr ctxt) { SV ** func; int count; SV * results; STRLEN results_len; const char * results_pv; xmlParserInputBufferPtr input_buf; if (ctxt->_private == NULL && EXTERNAL_ENTITY_LOADER_FUNC == NULL) { return xmlNewInputFromFile(ctxt, URL); } if (URL == NULL) { URL = ""; } if (ID == NULL) { ID = ""; } /* fetch entity loader function */ if(EXTERNAL_ENTITY_LOADER_FUNC != NULL) { func = &EXTERNAL_ENTITY_LOADER_FUNC; } else { SV * self; HV * real_obj; self = (SV *)ctxt->_private; real_obj = (HV *)SvRV(self); func = hv_fetch(real_obj, "ext_ent_handler", 15, 0); } if (func != NULL && SvTRUE(*func)) { dTHX; dSP; ENTER; SAVETMPS; PUSHMARK(SP) ; XPUSHs(sv_2mortal(newSVpv((char*)URL, 0))); XPUSHs(sv_2mortal(newSVpv((char*)ID, 0))); PUTBACK; count = call_sv(*func, G_SCALAR | G_EVAL); SPAGAIN; if (count == 0) { croak("external entity handler did not return a value"); } if (SvTRUE(ERRSV)) { (void) POPs; croak_obj; } results = POPs; results_pv = SvPV(results, results_len); input_buf = xmlParserInputBufferCreateMem( results_pv, results_len, XML_CHAR_ENCODING_NONE ); PUTBACK; FREETMPS; LEAVE; return xmlNewIOInputStream(ctxt, input_buf, XML_CHAR_ENCODING_NONE); } else { if (URL == NULL) { return NULL; } return xmlNewInputFromFile(ctxt, URL); } } /* **************************************************************** * Helper functions * **************************************************************** */ HV* LibXML_init_parser( SV * self, xmlParserCtxtPtr ctxt ) { /* we fetch all switches and callbacks from the hash */ HV* real_obj = NULL; SV** item = NULL; int parserOptions = XML_PARSE_NODICT; /* A NOTE ABOUT xmlInitParser(); */ /* xmlInitParser() should be used only at startup and*/ /* not for initializing a single parser. libxml2's */ /* documentation is quite clear about this. If */ /* something fails it is a problem elsewhere. Simply */ /* resetting the entire module will lead to unwanted */ /* results in server environments, such as if */ /* mod_perl is used together with php's xml module. */ /* calling xmlInitParser() here is definitely wrong! */ /* xmlInitParser(); */ #ifndef WITH_SERRORS xmlGetWarningsDefaultValue = 0; #endif if ( self != NULL ) { /* first fetch the values from the hash */ real_obj = (HV *)SvRV(self); item = hv_fetch( real_obj, "XML_LIBXML_PARSER_OPTIONS", 25, 0 ); if (item != NULL && SvOK(*item)) parserOptions = sv_2iv(*item); /* compatibility with old implementation: absence of XML_PARSE_DTDLOAD (load_ext_dtd) implies absence of all DTD related flags */ if ((parserOptions & XML_PARSE_DTDLOAD) == 0) { parserOptions &= ~(XML_PARSE_DTDVALID | XML_PARSE_DTDATTR | XML_PARSE_NOENT ); } if (ctxt) xmlCtxtUseOptions(ctxt, parserOptions ); /* Note: sets ctxt->linenumbers = 1 */ /* * Without this if/else conditional, NOBLANKS has no effect. * * For more information, see: * * https://rt.cpan.org/Ticket/Display.html?id=76696 * * */ if (parserOptions & XML_PARSE_NOBLANKS) { xmlKeepBlanksDefault(0); } else { xmlKeepBlanksDefault(1); } item = hv_fetch( real_obj, "XML_LIBXML_LINENUMBERS", 22, 0 ); if ( item != NULL && SvTRUE(*item) ) { if (ctxt) ctxt->linenumbers = 1; } else { if (ctxt) ctxt->linenumbers = 0; } if(EXTERNAL_ENTITY_LOADER_FUNC == NULL) { item = hv_fetch(real_obj, "ext_ent_handler", 15, 0); if (item != NULL && SvTRUE(*item)) { LibXML_old_ext_ent_loader = xmlGetExternalEntityLoader(); xmlSetExternalEntityLoader( (xmlExternalEntityLoader)LibXML_load_external_entity ); } else { if (parserOptions & XML_PARSE_NONET) { LibXML_old_ext_ent_loader = xmlGetExternalEntityLoader(); xmlSetExternalEntityLoader( xmlNoNetExternalEntityLoader ); } /* LibXML_old_ext_ent_loader = NULL; */ } } } return real_obj; } void LibXML_cleanup_parser() { #ifndef WITH_SERRORS xmlGetWarningsDefaultValue = 0; #endif if (EXTERNAL_ENTITY_LOADER_FUNC == NULL && LibXML_old_ext_ent_loader != NULL) { xmlSetExternalEntityLoader( (xmlExternalEntityLoader)LibXML_old_ext_ent_loader ); } } int LibXML_test_node_name( xmlChar * name ) { xmlChar * cur = name; int tc = 0; int len = 0; if ( cur == NULL || *cur == 0 ) { /* warn("name is empty" ); */ return(0); } tc = domParseChar( cur, &len ); if ( !( IS_LETTER( tc ) || (tc == '_') || (tc == ':')) ) { /* warn( "is not a letter\n" ); */ return(0); } tc = 0; cur += len; while (*cur != 0 ) { tc = domParseChar( cur, &len ); if (!(IS_LETTER(tc) || IS_DIGIT(tc) || (tc == '_') || (tc == '-') || (tc == ':') || (tc == '.') || IS_COMBINING(tc) || IS_EXTENDER(tc)) ) { /* warn( "is not a letter\n" ); */ return(0); } tc = 0; cur += len; } /* warn("name is ok"); */ return(1); } /* Assumes that the node has a proxy. */ static void LibXML_reparent_removed_node(xmlNodePtr node) { /* * Attribute nodes can't be added to document fragments. Adding * DTD nodes would cause a memory leak. */ if (node->type != XML_ATTRIBUTE_NODE && node->type != XML_DTD_NODE) { ProxyNodePtr docfrag = PmmNewFragment(node->doc); xmlAddChild(PmmNODE(docfrag), node); PmmFixOwner(PmmPROXYNODE(node), docfrag); } } static void LibXML_set_int_subset(xmlDocPtr doc, xmlNodePtr dtd) { xmlNodePtr old_dtd = (xmlNodePtr)doc->intSubset; if (old_dtd == dtd) { return; } if (old_dtd != NULL) { xmlUnlinkNode(old_dtd); if (PmmPROXYNODE(old_dtd) == NULL) { xmlFreeDtd((xmlDtdPtr)old_dtd); } } doc->intSubset = (xmlDtdPtr)dtd; } /* **************************************************************** * XPathContext helper functions * **************************************************************** */ /* Temporary node pool: * * Stores pnode in context node-pool hash table in order to preserve * * at least one reference. * * If pnode is NULL, only return current value for hashkey */ static SV* LibXML_XPathContext_pool ( xmlXPathContextPtr ctxt, void * hashkey, SV * pnode ) { SV ** value; SV * key; STRLEN len; char * strkey; dTHX; if (XPathContextDATA(ctxt)->pool == NULL) { if (pnode == NULL) { return &PL_sv_undef; } else { xs_warn("initializing node pool"); XPathContextDATA(ctxt)->pool = newHV(); } } key = newSViv(PTR2IV(hashkey)); strkey = SvPV(key, len); if (pnode != NULL && !hv_exists(XPathContextDATA(ctxt)->pool,strkey,len)) { value = hv_store(XPathContextDATA(ctxt)->pool,strkey,len, SvREFCNT_inc(pnode),0); } else { value = hv_fetch(XPathContextDATA(ctxt)->pool,strkey,len, 0); } SvREFCNT_dec(key); if (value == NULL) { return &PL_sv_undef; } else { return *value; } } /* convert perl result structures to LibXML structures */ static xmlXPathObjectPtr LibXML_perldata_to_LibXMLdata(xmlXPathParserContextPtr ctxt, SV* perl_result) { dTHX; if (!SvOK(perl_result)) { return (xmlXPathObjectPtr)xmlXPathNewCString(""); } if (SvROK(perl_result) && SvTYPE(SvRV(perl_result)) == SVt_PVAV) { /* consider any array ref to be a nodelist */ int i; int length; SV ** pnode; AV * array_result; xmlXPathObjectPtr ret; ret = (xmlXPathObjectPtr) xmlXPathNewNodeSet(INT2PTR(xmlNodePtr,NULL)); array_result = (AV*)SvRV(perl_result); length = av_len(array_result); for( i = 0; i <= length ; i++ ) { pnode = av_fetch(array_result,i,0); if (pnode != NULL && sv_isobject(*pnode) && sv_derived_from(*pnode,"XML::LibXML::Node")) { xmlXPathNodeSetAdd(ret->nodesetval, INT2PTR(xmlNodePtr,PmmSvNode(*pnode))); if(ctxt) { LibXML_XPathContext_pool(ctxt->context, PmmSvNode(*pnode), *pnode); } } else { warn("XPathContext: ignoring non-node member of a nodelist"); } } return ret; } else if (sv_isobject(perl_result) && (SvTYPE(SvRV(perl_result)) == SVt_PVMG)) { if (sv_derived_from(perl_result, "XML::LibXML::Node")) { xmlNodePtr tmp_node; xmlXPathObjectPtr ret; ret = INT2PTR(xmlXPathObjectPtr,xmlXPathNewNodeSet(NULL)); tmp_node = INT2PTR(xmlNodePtr,PmmSvNode(perl_result)); xmlXPathNodeSetAdd(ret->nodesetval,tmp_node); if(ctxt) { LibXML_XPathContext_pool(ctxt->context, PmmSvNode(perl_result), perl_result); } return ret; } else if (sv_isa(perl_result, "XML::LibXML::Boolean")) { return (xmlXPathObjectPtr) xmlXPathNewBoolean(SvIV(SvRV(perl_result))); } else if (sv_isa(perl_result, "XML::LibXML::Literal")) { return (xmlXPathObjectPtr) xmlXPathNewCString(SvPV_nolen(SvRV(perl_result))); } else if (sv_isa(perl_result, "XML::LibXML::Number")) { return (xmlXPathObjectPtr) xmlXPathNewFloat(SvNV(SvRV(perl_result))); } } else if (SvNOK(perl_result) || SvIOK(perl_result)) { return (xmlXPathObjectPtr)xmlXPathNewFloat(SvNV(perl_result)); } else { return (xmlXPathObjectPtr) xmlXPathNewCString(SvPV_nolen(perl_result)); } return NULL; } /* save XPath context and XPathContextDATA for recursion */ static xmlXPathContextPtr LibXML_save_context(xmlXPathContextPtr ctxt) { xmlXPathContextPtr copy; copy = xmlMalloc(sizeof(xmlXPathContext)); if (copy) { /* backup ctxt */ memcpy(copy, ctxt, sizeof(xmlXPathContext)); /* clear namespaces so that they are not freed and overwritten by configure_namespaces */ ctxt->namespaces = NULL; /* backup data */ copy->user = xmlMalloc(sizeof(XPathContextData)); if (XPathContextDATA(copy)) { memcpy(XPathContextDATA(copy), XPathContextDATA(ctxt),sizeof(XPathContextData)); /* clear ctxt->pool, so that it is not used freed during re-entrance */ XPathContextDATA(ctxt)->pool = NULL; } } return copy; } /* restore XPath context and XPathContextDATA from a saved copy */ static void LibXML_restore_context(xmlXPathContextPtr ctxt, xmlXPathContextPtr copy) { dTHX; /* cleanup */ if (XPathContextDATA(ctxt)) { /* cleanup newly created pool */ if (XPathContextDATA(ctxt)->pool != NULL && SvOK(XPathContextDATA(ctxt)->pool)) { SvREFCNT_dec((SV *)XPathContextDATA(ctxt)->pool); } } if (ctxt->namespaces) { /* free namespaces allocated during recursion */ xmlFree( ctxt->namespaces ); } /* restore context */ if (copy) { /* 1st restore our data */ if (XPathContextDATA(copy)) { memcpy(XPathContextDATA(ctxt),XPathContextDATA(copy),sizeof(XPathContextData)); xmlFree(XPathContextDATA(copy)); copy->user = XPathContextDATA(ctxt); } /* now copy the rest */ memcpy(ctxt, copy, sizeof(xmlXPathContext)); xmlFree(copy); } } /* **************************************************************** * Variable Lookup * **************************************************************** */ /* Much of the code is borrowed from Matt Sergeant's XML::LibXSLT */ static xmlXPathObjectPtr LibXML_generic_variable_lookup(void* varLookupData, const xmlChar *name, const xmlChar *ns_uri) { xmlXPathObjectPtr ret; xmlXPathContextPtr ctxt; xmlXPathContextPtr copy; XPathContextDataPtr data; I32 count; dTHX; dSP; ctxt = (xmlXPathContextPtr) varLookupData; if ( ctxt == NULL ) croak("XPathContext: missing xpath context"); data = XPathContextDATA(ctxt); if ( data == NULL ) croak("XPathContext: missing xpath context private data"); if ( data->varLookup == NULL || !SvROK(data->varLookup) || SvTYPE(SvRV(data->varLookup)) != SVt_PVCV ) croak("XPathContext: lost variable lookup function!"); ENTER; SAVETMPS; PUSHMARK(SP); XPUSHs( (data->varData != NULL) ? data->varData : &PL_sv_undef ); XPUSHs(sv_2mortal(C2Sv(name,NULL))); XPUSHs(sv_2mortal(C2Sv(ns_uri,NULL))); /* save context to allow recursive usage of XPathContext */ copy = LibXML_save_context(ctxt); PUTBACK ; count = call_sv(data->varLookup, G_SCALAR|G_EVAL); SPAGAIN; /* restore the xpath context */ LibXML_restore_context(ctxt, copy); if (SvTRUE(ERRSV)) { (void) POPs; croak_obj; } if (count != 1) croak("XPathContext: variable lookup function returned none or more than one argument!"); ret = LibXML_perldata_to_LibXMLdata(NULL, POPs); PUTBACK; FREETMPS; LEAVE; return ret; } /* **************************************************************** * Generic Extension Function * **************************************************************** */ /* Much of the code is borrowed from Matt Sergeant's XML::LibXSLT */ static void LibXML_generic_extension_function(xmlXPathParserContextPtr ctxt, int nargs) { xmlXPathObjectPtr obj,ret; xmlNodeSetPtr nodelist = NULL; int count; SV * perl_dispatch; int i; STRLEN len; ProxyNodePtr owner = NULL; SV *key; char *strkey; const char *function, *uri; SV **perl_function; dTHX; dSP; SV * data; xmlXPathContextPtr copy; /* warn("entered LibXML_generic_extension_function for %s\n",ctxt->context->function); */ data = (SV *) ctxt->context->funcLookupData; if (ctxt->context->funcLookupData == NULL || !SvROK(data) || SvTYPE(SvRV(data)) != SVt_PVHV) { croak("XPathContext: lost function lookup data structure!"); } function = (char*) ctxt->context->function; uri = (char*) ctxt->context->functionURI; key = newSVpvn("",0); if (uri && *uri) { sv_catpv(key, "{"); sv_catpv(key, (const char*)uri); sv_catpv(key, "}"); } sv_catpv(key, (const char*)function); strkey = SvPV(key, len); perl_function = hv_fetch((HV*)SvRV(data), strkey, len, 0); if ( perl_function == NULL || !SvOK(*perl_function) || !(SvPOK(*perl_function) || (SvROK(*perl_function) && SvTYPE(SvRV(*perl_function)) == SVt_PVCV))) { croak("XPathContext: lost perl extension function!"); } SvREFCNT_dec(key); ENTER; SAVETMPS; PUSHMARK(SP); XPUSHs(*perl_function); /* set up call to perl dispatcher function */ for (i = 0; i < nargs; i++) { obj = (xmlXPathObjectPtr)valuePop(ctxt); switch (obj->type) { case XPATH_XSLT_TREE: case XPATH_NODESET: nodelist = obj->nodesetval; if ( nodelist ) { XPUSHs(sv_2mortal(newSVpv("XML::LibXML::NodeList", 0))); XPUSHs(sv_2mortal(newSViv(nodelist->nodeNr))); if ( nodelist->nodeNr > 0 ) { int j; const char * cls = "XML::LibXML::Node"; xmlNodePtr tnode; SV * element; int l = nodelist->nodeNr; for( j = 0 ; j < l; j++){ tnode = nodelist->nodeTab[j]; if( tnode != NULL && tnode->doc != NULL) { owner = PmmOWNERPO(PmmNewNode(INT2PTR(xmlNodePtr,tnode->doc))); } else { owner = NULL; } if (tnode->type == XML_NAMESPACE_DECL) { element = NEWSV(0,0); cls = PmmNodeTypeName( tnode ); element = sv_setref_pv( element, (const char *)cls, (void *)xmlCopyNamespace((xmlNsPtr)tnode) ); } else { element = PmmNodeToSv(tnode, owner); } XPUSHs( sv_2mortal(element) ); } } } else { /* PP: We can't simply leave out an empty nodelist as Matt does! */ /* PP: The number of arguments must match! */ XPUSHs(sv_2mortal(newSVpv("XML::LibXML::NodeList", 0))); XPUSHs(sv_2mortal(newSViv(0))); } /* prevent libxml2 from freeing the actual nodes */ if (obj->boolval) obj->boolval=0; break; case XPATH_BOOLEAN: XPUSHs(sv_2mortal(newSVpv("XML::LibXML::Boolean", 0))); XPUSHs(sv_2mortal(newSViv(obj->boolval))); break; case XPATH_NUMBER: XPUSHs(sv_2mortal(newSVpv("XML::LibXML::Number", 0))); XPUSHs(sv_2mortal(newSVnv(obj->floatval))); break; case XPATH_STRING: XPUSHs(sv_2mortal(newSVpv("XML::LibXML::Literal", 0))); XPUSHs(sv_2mortal(C2Sv(obj->stringval, 0))); break; default: warn("Unknown XPath return type (%d) in call to {%s}%s - assuming string", obj->type, uri, function); XPUSHs(sv_2mortal(newSVpv("XML::LibXML::Literal", 0))); XPUSHs(sv_2mortal(C2Sv(xmlXPathCastToString(obj), 0))); } xmlXPathFreeObject(obj); } /* save context to allow recursive usage of XPathContext */ copy = LibXML_save_context(ctxt->context); /* call perl dispatcher */ PUTBACK; perl_dispatch = sv_2mortal(newSVpv("XML::LibXML::XPathContext::_perl_dispatcher",0)); count = call_sv(perl_dispatch, G_SCALAR|G_EVAL); SPAGAIN; /* restore the xpath context */ LibXML_restore_context(ctxt->context, copy); if (SvTRUE(ERRSV)) { (void) POPs; croak_obj; } if (count != 1) croak("XPathContext: perl-dispatcher in pm file returned none or more than one argument!"); ret = LibXML_perldata_to_LibXMLdata(ctxt, POPs); valuePush(ctxt, ret); PUTBACK; FREETMPS; LEAVE; } static void LibXML_configure_namespaces( xmlXPathContextPtr ctxt ) { xmlNodePtr node = ctxt->node; if (ctxt->namespaces != NULL) { xmlFree( ctxt->namespaces ); ctxt->namespaces = NULL; } if (node != NULL) { if (node->type == XML_DOCUMENT_NODE) { ctxt->namespaces = xmlGetNsList( node->doc, xmlDocGetRootElement( node->doc ) ); } else { ctxt->namespaces = xmlGetNsList(node->doc, node); } ctxt->nsNr = 0; if (ctxt->namespaces != NULL) { int cur=0; xmlNsPtr ns; /* we now walk through the list and drop every ns that was declared via registration */ while (ctxt->namespaces[cur] != NULL) { ns = ctxt->namespaces[cur]; if (ns->prefix==NULL || xmlHashLookup(ctxt->nsHash, ns->prefix) != NULL) { /* drop it */ ctxt->namespaces[cur]=NULL; } else { if (cur != ctxt->nsNr) { /* move the item to the new tail */ ctxt->namespaces[ctxt->nsNr]=ns; ctxt->namespaces[cur]=NULL; } ctxt->nsNr++; } cur++; } } } } static void LibXML_configure_xpathcontext( xmlXPathContextPtr ctxt ) { xmlNodePtr node = PmmSvNode(XPathContextDATA(ctxt)->node); if (node != NULL) { ctxt->doc = node->doc; } else { ctxt->doc = NULL; } ctxt->node = node; LibXML_configure_namespaces(ctxt); } #ifdef HAVE_READER_SUPPORT static void LibXML_set_reader_preserve_flag( xmlTextReaderPtr reader ) { HV *hash; char key[32]; hash = get_hv("XML::LibXML::Reader::_preserve_flag", 0); if (!hash) { return; } (void) snprintf(key, sizeof(key), "%p", reader); (void) hv_store(hash, key, strlen(key), newSV(0), 0); } static int LibXML_get_reader_preserve_flag( xmlTextReaderPtr reader ) { HV *hash; char key[32]; hash = get_hv("XML::LibXML::Reader::_preserve_flag", 0); if (!hash) { return 0; } (void) snprintf(key, sizeof(key), "%p", reader); if ( hv_exists(hash, key, strlen(key)) ) { (void) hv_delete(hash, key, strlen(key), G_DISCARD); return 1; } return 0; } #endif /* HAVE_READER_SUPPORT */ extern void boot_XML__LibXML__Devel(pTHX_ CV*); MODULE = XML::LibXML PACKAGE = XML::LibXML PROTOTYPES: DISABLE BOOT: /* Load Devel first, so debug_memory can be called before any allocation. */ /* The ++ is a bit hacky, but boot_blahblah_Devel, being an * XSUB body, will try to pop once more the mark we have just * (implicitly) popped, this boot sector also being an XSUB body */ PL_markstack_ptr++; boot_XML__LibXML__Devel(aTHX_ cv); LIBXML_TEST_VERSION xmlInitParser(); PmmSAXInitialize(aTHX); #ifndef WITH_SERRORS xmlGetWarningsDefaultValue = 0; #endif #ifdef LIBXML_CATALOG_ENABLED /* xmlCatalogSetDebug(10); */ xmlInitializeCatalog(); /* use catalog data */ #endif void _CLONE( class ) CODE: #ifdef XML_LIBXML_THREADS if( PmmUSEREGISTRY ) PmmCloneProxyNodes(); #endif int _leaked_nodes() CODE: RETVAL = 0; #ifdef XML_LIBXML_THREADS if( PmmUSEREGISTRY ) RETVAL = PmmProxyNodeRegistrySize(); #endif OUTPUT: RETVAL void _dump_registry() PPCODE: #ifdef XML_LIBXML_THREADS if( PmmUSEREGISTRY ) PmmDumpRegistry(PmmREGISTRY); #endif const char * LIBXML_DOTTED_VERSION() CODE: RETVAL = LIBXML_DOTTED_VERSION; OUTPUT: RETVAL int LIBXML_VERSION() CODE: RETVAL = LIBXML_VERSION; OUTPUT: RETVAL int HAVE_STRUCT_ERRORS() CODE: #ifdef WITH_SERRORS RETVAL = 1; #else RETVAL = 0; #endif OUTPUT: RETVAL int HAVE_SCHEMAS() CODE: #ifdef HAVE_SCHEMAS RETVAL = 1; # if LIBXML_VERSION == 20904 /* exists but broken https://github.com/shlomif/libxml2-2.9.4-reader-schema-regression */ RETVAL = 0; # endif #else RETVAL = 0; #endif OUTPUT: RETVAL int HAVE_READER() CODE: #ifdef HAVE_READER_SUPPORT RETVAL = 1; #else RETVAL = 0; #endif OUTPUT: RETVAL int HAVE_THREAD_SUPPORT() CODE: #ifdef XML_LIBXML_THREADS RETVAL = (PmmUSEREGISTRY ? 1 : 0); #else RETVAL = 0; #endif OUTPUT: RETVAL const char * LIBXML_RUNTIME_VERSION() CODE: RETVAL = xmlParserVersion; OUTPUT: RETVAL void END() CODE: xmlCleanupParser(); int INIT_THREAD_SUPPORT() CODE: #ifdef XML_LIBXML_THREADS SV *threads = get_sv("threads::threads", 0); /* no create */ if( threads && SvOK(threads) && SvTRUE(threads) ) { PROXY_NODE_REGISTRY_MUTEX = get_sv("XML::LibXML::__PROXY_NODE_REGISTRY_MUTEX",0); RETVAL = 1; } else { croak("XML::LibXML ':threads_shared' can only be used after 'use threads'"); } #else RETVAL = 0; #endif OUTPUT: RETVAL void DISABLE_THREAD_SUPPORT() CODE: #ifdef XML_LIBXML_THREADS PROXY_NODE_REGISTRY_MUTEX = NULL; #else croak("XML::LibXML compiled without threads!"); #endif SV* _parse_string(self, string, dir = &PL_sv_undef) SV * self SV * string SV * dir PREINIT: char * directory = NULL; STRLEN len; const char * ptr; HV * real_obj; int well_formed; int valid; int validate; xmlDocPtr real_doc; int recover = 0; PREINIT_SAVED_ERROR INIT: if (SvPOK(dir)) { directory = SvPV(dir, len); if (len <= 0) { directory = NULL; } } /* If string is a reference to a string - dereference it. * See: https://rt.cpan.org/Ticket/Display.html?id=64051 (broke it) * https://rt.cpan.org/Ticket/Display.html?id=77864 (fixed it) */ if (SvROK(string) && !SvOBJECT(SvRV(string))) { string = SvRV(string); } ptr = SvPV_const(string, len); if (len <= 0) { croak("Empty string\n"); XSRETURN_UNDEF; } CODE: RETVAL = &PL_sv_undef; INIT_ERROR_HANDLER; { xmlParserCtxtPtr ctxt = xmlCreateMemoryParserCtxt(ptr, len); if (ctxt == NULL) { CLEANUP_ERROR_HANDLER; REPORT_ERROR(1); croak("Could not create memory parser context!\n"); } xs_warn( "context created\n"); real_obj = LibXML_init_parser(self, ctxt); recover = LibXML_get_recover(real_obj); if ( directory != NULL ) { ctxt->directory = directory; } ctxt->_private = (void*)self; /* make libxml2-2.6 display line number on error */ if ( ctxt->input != NULL ) { if (directory != NULL) { ctxt->input->filename = (char *) xmlStrdup((const xmlChar *) directory); } else { ctxt->input->filename = (char *) xmlStrdup((const xmlChar *) ""); } } xs_warn( "context initialized\n" ); xmlParseDocument(ctxt); xs_warn( "document parsed \n"); ctxt->directory = NULL; well_formed = ctxt->wellFormed; valid = ctxt->valid; validate = ctxt->validate; real_doc = ctxt->myDoc; ctxt->myDoc = NULL; xmlFreeParserCtxt(ctxt); } if ( real_doc != NULL ) { if (real_doc->URL != NULL) { /* free "" assigned above */ xmlFree((char*) real_doc->URL); real_doc->URL = NULL; } if ( directory == NULL ) { SV * newURI = sv_2mortal(newSVpvf("unknown-%p", (void*)real_doc)); real_doc->URL = xmlStrdup((const xmlChar*)SvPV_nolen(newURI)); } else { real_doc->URL = xmlStrdup((const xmlChar*)directory); } if ( ! LibXML_will_die_ctx(saved_error, recover) && (recover || ( well_formed && ( !validate || ( valid || ( real_doc->intSubset == NULL && real_doc->extSubset == NULL )))))) { RETVAL = LibXML_NodeToSv( real_obj, INT2PTR(xmlNodePtr,real_doc) ); } else { xmlFreeDoc(real_doc); real_doc=NULL; } } LibXML_cleanup_parser(); CLEANUP_ERROR_HANDLER; REPORT_ERROR(recover); OUTPUT: RETVAL int _parse_sax_string(self, string) SV * self SV * string PREINIT: STRLEN len; char * ptr; HV * real_obj; int recover = 0; PREINIT_SAVED_ERROR INIT: ptr = SvPV(string, len); if (len <= 0) { croak("Empty string\n"); XSRETURN_UNDEF; } CODE: RETVAL = 0; INIT_ERROR_HANDLER; { xmlParserCtxtPtr ctxt = xmlCreateMemoryParserCtxt((const char*)ptr, len); if (ctxt == NULL) { CLEANUP_ERROR_HANDLER; REPORT_ERROR(recover ? recover : 1); croak("Could not create memory parser context!\n"); } xs_warn( "context created\n"); real_obj = LibXML_init_parser(self, ctxt); recover = LibXML_get_recover(real_obj); PmmSAXInitContext( ctxt, self, saved_error ); xs_warn( "context initialized \n"); { RETVAL = xmlParseDocument(ctxt); xs_warn( "document parsed \n"); } PmmSAXCloseContext(ctxt); xmlFreeParserCtxt(ctxt); } LibXML_cleanup_parser(); CLEANUP_ERROR_HANDLER; REPORT_ERROR(recover); OUTPUT: RETVAL SV* _parse_fh(self, fh, dir = &PL_sv_undef) SV * self SV * fh SV * dir PREINIT: STRLEN len; char * directory = NULL; HV * real_obj; int well_formed; int valid; int validate; xmlDocPtr real_doc; int recover = 0; PREINIT_SAVED_ERROR INIT: if (SvPOK(dir)) { directory = SvPV(dir, len); if (len <= 0) { directory = NULL; } } CODE: RETVAL = &PL_sv_undef; INIT_ERROR_HANDLER; { int read_length; char buffer[1024]; xmlParserCtxtPtr ctxt; read_length = LibXML_read_perl(fh, buffer, 4); if (read_length <= 0) { CLEANUP_ERROR_HANDLER; croak( "Empty Stream\n" ); } ctxt = xmlCreatePushParserCtxt(NULL, NULL, buffer, read_length, NULL); if (ctxt == NULL) { CLEANUP_ERROR_HANDLER; REPORT_ERROR(1); croak("Could not create xml push parser context!\n"); } xs_warn( "context created\n"); real_obj = LibXML_init_parser(self, ctxt); recover = LibXML_get_recover(real_obj); #if LIBXML_VERSION > 20600 /* dictionaries not support yet */ ctxt->dictNames = 0; #endif if ( directory != NULL ) { ctxt->directory = directory; } ctxt->_private = (void*)self; xs_warn( "context initialized \n"); { int ret; while ((read_length = LibXML_read_perl(fh, buffer, 1024))) { ret = xmlParseChunk(ctxt, buffer, read_length, 0); if ( ret != 0 ) { break; } } ret = xmlParseChunk(ctxt, buffer, 0, 1); xs_warn( "document parsed \n"); } ctxt->directory = NULL; well_formed = ctxt->wellFormed; valid = ctxt->valid; validate = ctxt->validate; real_doc = ctxt->myDoc; ctxt->myDoc = NULL; xmlFreeParserCtxt(ctxt); } if ( real_doc != NULL ) { if ( directory == NULL ) { SV * newURI = sv_2mortal(newSVpvf("unknown-%p", (void*)real_doc)); real_doc->URL = xmlStrdup((const xmlChar*)SvPV_nolen(newURI)); } else { real_doc->URL = xmlStrdup((const xmlChar*)directory); } if ( ! LibXML_will_die_ctx(saved_error, recover) && (recover || ( well_formed && ( !validate || ( valid || ( real_doc->intSubset == NULL && real_doc->extSubset == NULL )))))) { RETVAL = LibXML_NodeToSv( real_obj, INT2PTR(xmlNodePtr,real_doc) ); } else { xmlFreeDoc(real_doc); real_doc=NULL; } } LibXML_cleanup_parser(); CLEANUP_ERROR_HANDLER; REPORT_ERROR(recover); OUTPUT: RETVAL void _parse_sax_fh(self, fh, dir = &PL_sv_undef) SV * self SV * fh SV * dir PREINIT: STRLEN len; char * directory = NULL; HV * real_obj; int recover = 0; PREINIT_SAVED_ERROR INIT: if (SvPOK(dir)) { directory = SvPV(dir, len); if (len <= 0) { directory = NULL; } } CODE: INIT_ERROR_HANDLER; { int read_length; char buffer[1024]; xmlSAXHandlerPtr sax; xmlParserCtxtPtr ctxt; read_length = LibXML_read_perl(fh, buffer, 4); if (read_length <= 0) { CLEANUP_ERROR_HANDLER; croak( "Empty Stream\n" ); } sax = PSaxGetHandler(); ctxt = xmlCreatePushParserCtxt(sax, NULL, buffer, read_length, NULL); if (ctxt == NULL) { CLEANUP_ERROR_HANDLER; REPORT_ERROR(recover ? recover : 1); croak("Could not create xml push parser context!\n"); } xs_warn( "context created\n"); real_obj = LibXML_init_parser(self, ctxt); recover = LibXML_get_recover(real_obj); if ( directory != NULL ) { ctxt->directory = directory; } PmmSAXInitContext( ctxt, self, saved_error ); xs_warn( "context initialized \n"); { int ret; while ((read_length = LibXML_read_perl(fh, buffer, 1024))) { ret = xmlParseChunk(ctxt, buffer, read_length, 0); if ( ret != 0 ) { break; } } ret = xmlParseChunk(ctxt, buffer, 0, 1); xs_warn( "document parsed \n"); } ctxt->directory = NULL; xmlFree(ctxt->sax); ctxt->sax = NULL; xmlFree(sax); PmmSAXCloseContext(ctxt); xmlFreeParserCtxt(ctxt); } CLEANUP_ERROR_HANDLER; LibXML_cleanup_parser(); REPORT_ERROR(recover); SV* _parse_file(self, filename_sv) SV * self SV * filename_sv PREINIT: STRLEN len; char * filename; HV * real_obj; int well_formed; int valid; int validate; xmlDocPtr real_doc; int recover = 0; PREINIT_SAVED_ERROR INIT: filename = SvPV(filename_sv, len); if (len <= 0) { croak("Empty filename\n"); XSRETURN_UNDEF; } CODE: RETVAL = &PL_sv_undef; INIT_ERROR_HANDLER; { xmlParserCtxtPtr ctxt = xmlCreateFileParserCtxt(filename); if (ctxt == NULL) { CLEANUP_ERROR_HANDLER; REPORT_ERROR(1); croak("Could not create file parser context for file \"%s\": %s\n", filename, strerror(errno)); } xs_warn( "context created\n"); real_obj = LibXML_init_parser(self, ctxt); recover = LibXML_get_recover(real_obj); ctxt->_private = (void*)self; xs_warn( "context initialized\n" ); xmlParseDocument(ctxt); xs_warn( "document parsed \n"); well_formed = ctxt->wellFormed; valid = ctxt->valid; validate = ctxt->validate; real_doc = ctxt->myDoc; ctxt->myDoc = NULL; xmlFreeParserCtxt(ctxt); } if ( real_doc != NULL ) { if ( ! LibXML_will_die_ctx(saved_error, recover) && (recover || ( well_formed && ( !validate || ( valid || ( real_doc->intSubset == NULL && real_doc->extSubset == NULL )))))) { RETVAL = LibXML_NodeToSv( real_obj, INT2PTR(xmlNodePtr,real_doc) ); } else { xmlFreeDoc(real_doc); real_doc=NULL; } } LibXML_cleanup_parser(); CLEANUP_ERROR_HANDLER; REPORT_ERROR(recover); OUTPUT: RETVAL void _parse_sax_file(self, filename_sv) SV * self SV * filename_sv PREINIT: STRLEN len; char * filename; HV * real_obj; int recover = 0; PREINIT_SAVED_ERROR INIT: filename = SvPV(filename_sv, len); if (len <= 0) { croak("Empty filename\n"); XSRETURN_UNDEF; } CODE: INIT_ERROR_HANDLER; { xmlParserCtxtPtr ctxt = xmlCreateFileParserCtxt(filename); if (ctxt == NULL) { CLEANUP_ERROR_HANDLER; REPORT_ERROR(recover ? recover : 1); croak("Could not create file parser context for file \"%s\": %s\n", filename, strerror(errno)); } xs_warn( "context created\n"); real_obj = LibXML_init_parser(self, ctxt); recover = LibXML_get_recover(real_obj); ctxt->sax = PSaxGetHandler(); PmmSAXInitContext( ctxt, self, saved_error ); xs_warn( "context initialized \n"); { xmlParseDocument(ctxt); xs_warn( "document parsed \n"); } PmmSAXCloseContext(ctxt); xmlFreeParserCtxt(ctxt); } LibXML_cleanup_parser(); CLEANUP_ERROR_HANDLER; REPORT_ERROR(recover); SV* _parse_html_string(self, string, svURL, svEncoding, options = 0) SV * self SV * string SV * svURL SV * svEncoding int options PREINIT: STRLEN len; char * ptr; char* URL = NULL; const char * encoding = NULL; HV * real_obj; htmlDocPtr real_doc; int recover = 0; PREINIT_SAVED_ERROR INIT: /* If string is a reference to a string - dereference it. * See: https://rt.cpan.org/Ticket/Display.html?id=64051 (broke it) * https://rt.cpan.org/Ticket/Display.html?id=77864 (fixed it) */ if (SvROK(string) && !SvOBJECT(SvRV(string))) { string = SvRV(string); } ptr = SvPV(string, len); if (len <= 0) { croak("Empty string\n"); XSRETURN_UNDEF; } if (SvOK(svURL)) URL = SvPV_nolen( svURL ); if (SvOK(svEncoding)) encoding = SvPV_nolen( svEncoding ); CODE: RETVAL = &PL_sv_undef; INIT_ERROR_HANDLER; real_obj = LibXML_init_parser(self,NULL); if (encoding == NULL && SvUTF8( string )) { encoding = "UTF-8"; } if (options & HTML_PARSE_RECOVER) { recover = ((options & HTML_PARSE_NOERROR) ? 2 : 1); } #if LIBXML_VERSION >= 20627 real_doc = htmlReadDoc((xmlChar*)ptr, URL, encoding, options); #else real_doc = htmlParseDoc((xmlChar*)ptr, encoding); if ( real_doc ) { if (real_doc->URL) xmlFree((xmlChar *)real_doc->URL); if (URL) { real_doc->URL = xmlStrdup((const xmlChar*) URL); } } #endif if ( real_doc ) { if (URL==NULL) { SV * newURI = sv_2mortal(newSVpvf("unknown-%p", (void*)real_doc)); real_doc->URL = xmlStrdup((const xmlChar*)SvPV_nolen(newURI)); } /* This HTML memory parser doesn't use a ctxt; there is no "well-formed" * distinction, and if it manages to parse the HTML, it returns non-null. */ RETVAL = LibXML_NodeToSv( real_obj, INT2PTR(xmlNodePtr,real_doc) ); } LibXML_cleanup_parser(); CLEANUP_ERROR_HANDLER; REPORT_ERROR(recover); OUTPUT: RETVAL SV* _parse_html_file(self, filename_sv, svURL, svEncoding, options = 0) SV * self SV * filename_sv SV * svURL SV * svEncoding int options PREINIT: STRLEN len; char * filename; char * URL = NULL; char * encoding = NULL; HV * real_obj; htmlDocPtr real_doc; int recover = 0; PREINIT_SAVED_ERROR INIT: filename = SvPV(filename_sv, len); if (len <= 0) { croak("Empty filename\n"); XSRETURN_UNDEF; } if (SvOK(svURL)) URL = SvPV_nolen( svURL ); if (SvOK(svEncoding)) encoding = SvPV_nolen( svEncoding ); CODE: RETVAL = &PL_sv_undef; INIT_ERROR_HANDLER; real_obj = LibXML_init_parser(self,NULL); if (options & HTML_PARSE_RECOVER) { recover = ((options & HTML_PARSE_NOERROR) ? 2 : 1); } #if LIBXML_VERSION >= 20627 real_doc = htmlReadFile((const char *)filename, encoding, options); #else real_doc = htmlParseFile((const char *)filename, encoding); #endif if ( real_doc != NULL ) { /* This HTML file parser doesn't use a ctxt; there is no "well-formed" * distinction, and if it manages to parse the HTML, it returns non-null. */ if (URL) { if (real_doc->URL) xmlFree((xmlChar*) real_doc->URL); real_doc->URL = xmlStrdup((const xmlChar*) URL); } RETVAL = LibXML_NodeToSv( real_obj, INT2PTR(xmlNodePtr,real_doc) ); } CLEANUP_ERROR_HANDLER; LibXML_cleanup_parser(); REPORT_ERROR(recover); OUTPUT: RETVAL SV* _parse_html_fh(self, fh, svURL, svEncoding, options = 0) SV * self SV * fh SV * svURL SV * svEncoding int options PREINIT: HV * real_obj; htmlDocPtr real_doc; int recover = 0; char * URL = NULL; PREINIT_SAVED_ERROR #if LIBXML_VERSION >= 20627 char * encoding = NULL; #else xmlCharEncoding enc = XML_CHAR_ENCODING_NONE; #endif INIT: if (SvOK(svURL)) URL = SvPV_nolen( svURL ); #if LIBXML_VERSION >= 20627 if (SvOK(svEncoding)) encoding = SvPV_nolen( svEncoding ); #else if (SvOK(svEncoding)) enc = xmlParseCharEncoding(SvPV_nolen( svEncoding )); #endif CODE: RETVAL = &PL_sv_undef; INIT_ERROR_HANDLER; real_obj = LibXML_init_parser(self,NULL); if (options & HTML_PARSE_RECOVER) { recover = ((options & HTML_PARSE_NOERROR) ? 2 : 1); } #if LIBXML_VERSION >= 20627 real_doc = htmlReadIO((xmlInputReadCallback) LibXML_read_perl, NULL, (void *) fh, URL, encoding, options); #else /* LIBXML_VERSION >= 20627 */ { int read_length; int well_formed; char buffer[1024]; htmlParserCtxtPtr ctxt; read_length = LibXML_read_perl(fh, buffer, 4); if (read_length <= 0) { CLEANUP_ERROR_HANDLER; croak( "Empty Stream\n" ); } ctxt = htmlCreatePushParserCtxt(NULL, NULL, buffer, read_length, URL, enc); if (ctxt == NULL) { CLEANUP_ERROR_HANDLER; REPORT_ERROR(recover ? recover : 1); croak("Could not create html push parser context!\n"); } ctxt->_private = (void*)self; { int ret; while ((read_length = LibXML_read_perl(fh, buffer, 1024))) { ret = htmlParseChunk(ctxt, buffer, read_length, 0); if ( ret != 0 ) { break; } } ret = htmlParseChunk(ctxt, buffer, 0, 1); } well_formed = ctxt->wellFormed; real_doc = ctxt->myDoc; ctxt->myDoc = NULL; htmlFreeParserCtxt(ctxt); } #endif /* LIBXML_VERSION >= 20627 */ if ( real_doc != NULL ) { if (real_doc->URL) xmlFree((xmlChar*) real_doc->URL); if (URL) { real_doc->URL = xmlStrdup((const xmlChar*) URL); } else { SV * newURI = sv_2mortal(newSVpvf("unknown-%p", (void*)real_doc)); real_doc->URL = xmlStrdup((const xmlChar*)SvPV_nolen(newURI)); } RETVAL = LibXML_NodeToSv( real_obj, INT2PTR(xmlNodePtr,real_doc) ); } LibXML_cleanup_parser(); CLEANUP_ERROR_HANDLER; REPORT_ERROR(recover); OUTPUT: RETVAL SV* _parse_xml_chunk(self, svchunk, enc = &PL_sv_undef) SV * self SV * svchunk SV * enc PREINIT: STRLEN len; const char * encoding = "UTF-8"; HV * real_obj; int recover = 0; xmlChar * chunk; xmlNodePtr rv = NULL; PREINIT_SAVED_ERROR INIT: if (SvPOK(enc)) { encoding = SvPV(enc, len); if (len <= 0) { encoding = "UTF-8"; } } CODE: RETVAL = &PL_sv_undef; INIT_ERROR_HANDLER; real_obj = LibXML_init_parser(self,NULL); chunk = Sv2C(svchunk, (const xmlChar*)encoding); if ( chunk != NULL ) { recover = LibXML_get_recover(real_obj); rv = domReadWellBalancedString( NULL, chunk, recover ); if ( rv != NULL ) { xmlNodePtr fragment= NULL; xmlNodePtr rv_end = NULL; /* now we append the nodelist to a document fragment which is unbound to a Document!!!! */ /* step 1: create the fragment */ fragment = xmlNewDocFragment( NULL ); RETVAL = LibXML_NodeToSv(real_obj, fragment); /* step 2: set the node list to the fragment */ fragment->children = rv; rv_end = rv; while ( rv_end->next != NULL ) { rv_end->parent = fragment; rv_end = rv_end->next; } /* the following line is important, otherwise we'll have occasional segmentation faults */ rv_end->parent = fragment; fragment->last = rv_end; } /* free the chunk we created */ xmlFree( chunk ); } LibXML_cleanup_parser(); CLEANUP_ERROR_HANDLER; REPORT_ERROR(recover); if (rv == NULL) { croak("_parse_xml_chunk: chunk parsing failed\n"); } OUTPUT: RETVAL void _parse_sax_xml_chunk(self, svchunk, enc = &PL_sv_undef) SV * self SV * svchunk SV * enc PREINIT: STRLEN len; char * ptr; const char * encoding = "UTF-8"; HV * real_obj; int recover = 0; xmlChar * chunk; int retCode = -1; xmlNodePtr nodes = NULL; xmlSAXHandlerPtr handler = NULL; PREINIT_SAVED_ERROR INIT: if (SvPOK(enc)) { encoding = SvPV(enc, len); if (len <= 0) { encoding = "UTF-8"; } } ptr = SvPV(svchunk, len); if (len <= 0) { croak("Empty string\n"); } CODE: INIT_ERROR_HANDLER; chunk = Sv2C(svchunk, (const xmlChar*)encoding); if ( chunk != NULL ) { xmlParserCtxtPtr ctxt = xmlCreateMemoryParserCtxt((const char*)ptr, len); if (ctxt == NULL) { CLEANUP_ERROR_HANDLER; REPORT_ERROR(recover ? recover : 1); croak("Could not create memory parser context!\n"); } xs_warn( "context created\n"); real_obj = LibXML_init_parser(self,ctxt); recover = LibXML_get_recover(real_obj); PmmSAXInitContext( ctxt, self, saved_error ); handler = PSaxGetHandler(); retCode = xmlParseBalancedChunkMemory( NULL, handler, ctxt, 0, chunk, &nodes ); xmlFree( handler ); PmmSAXCloseContext(ctxt); xmlFreeParserCtxt(ctxt); /* free the chunk we created */ xmlFree( chunk ); } LibXML_cleanup_parser(); CLEANUP_ERROR_HANDLER; REPORT_ERROR(recover); if (retCode == -1) { croak("_parse_sax_xml_chunk: chunk parsing failed\n"); } int _processXIncludes(self, doc, options=0) SV * self SV * doc int options PREINIT: xmlDocPtr real_doc; HV * real_obj; int recover = 0; PREINIT_SAVED_ERROR INIT: real_doc = (xmlDocPtr) PmmSvNode(doc); if (real_doc == NULL) { croak("No document to process!\n"); XSRETURN_UNDEF; } CODE: RETVAL = 0; INIT_ERROR_HANDLER; real_obj = LibXML_init_parser(self,NULL); recover = LibXML_get_recover(real_obj); RETVAL = xmlXIncludeProcessFlags(real_doc,options); LibXML_cleanup_parser(); CLEANUP_ERROR_HANDLER; REPORT_ERROR(recover); if ( RETVAL < 0 ) { croak( "unknown error during XInclude processing\n" ); XSRETURN_UNDEF; } else if ( RETVAL == 0 ) { RETVAL = 1; } OUTPUT: RETVAL SV* _start_push(self, with_sax=0) SV * self int with_sax PREINIT: HV * real_obj; int recover = 0; xmlParserCtxtPtr ctxt = NULL; PREINIT_SAVED_ERROR CODE: RETVAL = &PL_sv_undef; INIT_ERROR_HANDLER; /* create empty context */ ctxt = xmlCreatePushParserCtxt( NULL, NULL, NULL, 0, NULL ); real_obj = LibXML_init_parser(self,ctxt); recover = LibXML_get_recover(real_obj); if ( with_sax == 1 ) { PmmSAXInitContext( ctxt, self, saved_error ); } RETVAL = PmmContextSv( ctxt ); LibXML_cleanup_parser(); CLEANUP_ERROR_HANDLER; REPORT_ERROR(recover); OUTPUT: RETVAL int _push(self, pctxt, data) SV * self SV * pctxt SV * data PREINIT: HV * real_obj; int recover = 0; xmlParserCtxtPtr ctxt = NULL; STRLEN len = 0; char * chunk = NULL; PREINIT_SAVED_ERROR INIT: ctxt = PmmSvContext( pctxt ); if ( ctxt == NULL ) { croak( "parser context already freed\n" ); XSRETURN_UNDEF; } if ( data == &PL_sv_undef ) { XSRETURN_UNDEF; } chunk = SvPV( data, len ); if ( len <= 0 ) { xs_warn( "empty string" ); XSRETURN_UNDEF; } CODE: RETVAL = 0; INIT_ERROR_HANDLER; real_obj = LibXML_init_parser(self,NULL); recover = LibXML_get_recover(real_obj); xmlParseChunk(ctxt, (const char *)chunk, len, 0); LibXML_cleanup_parser(); CLEANUP_ERROR_HANDLER; REPORT_ERROR(recover); if ( ctxt->wellFormed == 0 ) { croak( "XML not well-formed in xmlParseChunk\n" ); XSRETURN_UNDEF; } RETVAL = 1; OUTPUT: RETVAL SV* _end_push(self, pctxt, restore) SV * self SV * pctxt int restore PREINIT: HV * real_obj; int well_formed; xmlParserCtxtPtr ctxt = NULL; xmlDocPtr real_doc = NULL; PREINIT_SAVED_ERROR INIT: ctxt = PmmSvContext( pctxt ); if ( ctxt == NULL ) { croak( "parser context already freed\n" ); XSRETURN_UNDEF; } CODE: RETVAL = &PL_sv_undef; INIT_ERROR_HANDLER; real_obj = LibXML_init_parser(self,NULL); xmlParseChunk(ctxt, "", 0, 1); /* finish the parse */ xs_warn( "Finished with push parser\n" ); well_formed = ctxt->wellFormed; real_doc = ctxt->myDoc; ctxt->myDoc = NULL; xmlFreeParserCtxt(ctxt); PmmNODE( SvPROXYNODE( pctxt ) ) = NULL; if ( real_doc != NULL ) { if ( restore || well_formed ) { RETVAL = LibXML_NodeToSv( real_obj, INT2PTR(xmlNodePtr,real_doc) ); } else { xmlFreeDoc(real_doc); real_doc = NULL; } } LibXML_cleanup_parser(); CLEANUP_ERROR_HANDLER; REPORT_ERROR(restore); if ( real_doc == NULL ){ croak( "no document found!\n" ); XSRETURN_UNDEF; } OUTPUT: RETVAL void _end_sax_push(self, pctxt) SV * self SV * pctxt PREINIT: HV * real_obj; xmlParserCtxtPtr ctxt = NULL; PREINIT_SAVED_ERROR INIT: ctxt = PmmSvContext( pctxt ); if ( ctxt == NULL ) { croak( "parser context already freed\n" ); } CODE: INIT_ERROR_HANDLER; real_obj = LibXML_init_parser(self,NULL); xmlParseChunk(ctxt, "", 0, 1); /* finish the parse */ xs_warn( "Finished with SAX push parser\n" ); xmlFree(ctxt->sax); ctxt->sax = NULL; PmmSAXCloseContext(ctxt); xmlFreeParserCtxt(ctxt); PmmNODE( SvPROXYNODE( pctxt ) ) = NULL; LibXML_cleanup_parser(); CLEANUP_ERROR_HANDLER; REPORT_ERROR(0); SV* import_GDOME( CLASS, sv_gdome, deep=1 ) SV * sv_gdome int deep PREINIT: xmlNodePtr node = NULL; INIT: RETVAL = &PL_sv_undef; #ifndef XML_LIBXML_GDOME_SUPPORT croak( "GDOME Support not compiled" ); #endif if ( sv_gdome == NULL || sv_gdome == &PL_sv_undef ) { croak( "no XML::GDOME data found" ); } #ifdef XML_LIBXML_GDOME_SUPPORT else { GdomeNode* gnode = NULL; gnode = (GdomeNode*)SvIV((SV*)SvRV( sv_gdome )); if ( gnode == NULL ) { croak( "no XML::GDOME data found (datastructure empty)" ); } node = gdome_xml_n_get_xmlNode( gnode ); if ( node == NULL ) { croak( "no XML::LibXML node found in GDOME object" ); } } #endif CODE: if ( node->type == XML_NAMESPACE_DECL ) { const char * CLASS = "XML::LibXML::Namespace"; RETVAL = NEWSV(0,0); RETVAL = sv_setref_pv( RETVAL, CLASS, (void*)xmlCopyNamespace((xmlNsPtr)node) ); } else { RETVAL = PmmNodeToSv( PmmCloneNode( node, deep ), NULL ); } OUTPUT: RETVAL SV* export_GDOME( CLASS, sv_libxml, deep=1 ) SV * sv_libxml int deep PREINIT: xmlNodePtr node = NULL, retnode = NULL; INIT: RETVAL = &PL_sv_undef; #ifndef XML_LIBXML_GDOME_SUPPORT croak( "GDOME Support not configured!" ); #endif if ( sv_libxml == NULL || sv_libxml == &PL_sv_undef ) { croak( "no XML::LibXML data found" ); } node = PmmSvNode( sv_libxml ); if ( node == NULL ) { croak( "no XML::LibXML data found (empty structure)" ); } CODE: retnode = PmmCloneNode( node, deep ); if ( retnode == NULL ) { croak( "Copy node failed" ); } RETVAL = PmmNodeToGdomeSv( retnode ); OUTPUT: RETVAL int load_catalog( self, filename ) SV * filename PREINIT: const char * fn = (const char *) Sv2C(filename, NULL); INIT: if ( fn == NULL || xmlStrlen( (xmlChar *)fn ) == 0 ) { croak( "cannot load catalog" ); } CODE: #ifdef LIBXML_CATALOG_ENABLED RETVAL = xmlLoadCatalog( fn ); #else XSRETURN_UNDEF; #endif OUTPUT: RETVAL int _default_catalog( self, catalog ) SV * catalog PREINIT: #ifdef LIBXML_CATALOG_ENABLED xmlCatalogPtr catal = INT2PTR(xmlCatalogPtr,SvIV(SvRV(catalog))); #endif INIT: if ( catal == NULL ) { croak( "empty catalog\n" ); } CODE: warn( "this feature is not implemented" ); RETVAL = 0; OUTPUT: RETVAL SV* _externalEntityLoader( loader ) SV* loader CODE: { RETVAL = EXTERNAL_ENTITY_LOADER_FUNC; if(EXTERNAL_ENTITY_LOADER_FUNC == NULL) { EXTERNAL_ENTITY_LOADER_FUNC = newSVsv(loader); } if (LibXML_old_ext_ent_loader == NULL ) { LibXML_old_ext_ent_loader = xmlGetExternalEntityLoader(); xmlSetExternalEntityLoader((xmlExternalEntityLoader)LibXML_load_external_entity); } } OUTPUT: RETVAL MODULE = XML::LibXML PACKAGE = XML::LibXML::HashTable xmlHashTablePtr new(CLASS) const char * CLASS CODE: RETVAL = xmlHashCreate(8); OUTPUT: RETVAL void DESTROY( table ) xmlHashTablePtr table CODE: xs_warn("DESTROY XMLHASHTABLE\n"); PmmFreeHashTable(table); MODULE = XML::LibXML PACKAGE = XML::LibXML::ParserContext void DESTROY( self ) SV * self CODE: xs_warn( "DROP PARSER CONTEXT!" ); PmmContextREFCNT_dec( SvPROXYNODE( self ) ); MODULE = XML::LibXML PACKAGE = XML::LibXML::Document SV * _toString(self, format=0) xmlDocPtr self int format PREINIT: xmlChar *result=NULL; int len=0; SV* internalFlag = NULL; int oldTagFlag = xmlSaveNoEmptyTags; xmlDtdPtr intSubset = NULL; /* PREINIT_SAVED_ERROR */ CODE: RETVAL = &PL_sv_undef; internalFlag = get_sv("XML::LibXML::setTagCompression", 0); if( internalFlag ) { xmlSaveNoEmptyTags = SvTRUE(internalFlag); } internalFlag = get_sv("XML::LibXML::skipDTD", 0); if ( internalFlag && SvTRUE(internalFlag) ) { intSubset = xmlGetIntSubset( self ); if ( intSubset ) xmlUnlinkNode( INT2PTR(xmlNodePtr,intSubset) ); } /* INIT_ERROR_HANDLER; */ if ( format <= 0 ) { xs_warn( "use no formated toString!" ); xmlDocDumpMemory(self, &result, &len); } else { int t_indent_var = xmlIndentTreeOutput; xs_warn( "use formated toString!" ); xmlIndentTreeOutput = 1; xmlDocDumpFormatMemory( self, &result, &len, format ); xmlIndentTreeOutput = t_indent_var; } if ( intSubset != NULL ) { if (self->children == NULL) { xmlAddChild(INT2PTR(xmlNodePtr,self), INT2PTR(xmlNodePtr,intSubset)); } else { xmlAddPrevSibling(self->children, INT2PTR(xmlNodePtr,intSubset)); } } xmlSaveNoEmptyTags = oldTagFlag; /* REPORT_ERROR(0); */ if (result == NULL) { xs_warn("Failed to convert doc to string"); XSRETURN_UNDEF; } else { /* warn("%s, %d\n",result, len); */ RETVAL = newSVpvn( (const char *)result, len ); /* C2Sv( result, self->encoding ); */ xmlFree(result); } OUTPUT: RETVAL int toFH( self, filehandler, format=0 ) xmlDocPtr self SV * filehandler int format PREINIT: xmlOutputBufferPtr buffer; const xmlChar * encoding = NULL; xmlCharEncodingHandlerPtr handler = NULL; SV* internalFlag = NULL; int oldTagFlag = xmlSaveNoEmptyTags; xmlDtdPtr intSubset = NULL; int t_indent_var = xmlIndentTreeOutput; PREINIT_SAVED_ERROR CODE: internalFlag = get_sv("XML::LibXML::setTagCompression", 0); if( internalFlag ) { xmlSaveNoEmptyTags = SvTRUE(internalFlag); } internalFlag = get_sv("XML::LibXML::skipDTD", 0); if ( internalFlag && SvTRUE(internalFlag) ) { intSubset = xmlGetIntSubset( self ); if ( intSubset ) xmlUnlinkNode( INT2PTR(xmlNodePtr,intSubset) ); } xmlRegisterDefaultOutputCallbacks(); encoding = (self)->encoding; if ( encoding != NULL ) { if ( xmlParseCharEncoding((const char*)encoding) != XML_CHAR_ENCODING_UTF8) { handler = xmlFindCharEncodingHandler((const char*)encoding); } } else { xs_warn("no encoding?"); } buffer = xmlOutputBufferCreateIO( (xmlOutputWriteCallback) &LibXML_output_write_handler, (xmlOutputCloseCallback)&LibXML_output_close_handler, filehandler, handler ); if ( format <= 0 ) { format = 0; xmlIndentTreeOutput = 0; } else { xmlIndentTreeOutput = 1; } INIT_ERROR_HANDLER; RETVAL = xmlSaveFormatFileTo( buffer, self, (const char *) encoding, format); if ( intSubset != NULL ) { if (self->children == NULL) { xmlAddChild(INT2PTR(xmlNodePtr,self), INT2PTR(xmlNodePtr,intSubset)); } else { xmlAddPrevSibling(self->children, INT2PTR(xmlNodePtr,intSubset)); } } xmlIndentTreeOutput = t_indent_var; xmlSaveNoEmptyTags = oldTagFlag; CLEANUP_ERROR_HANDLER; REPORT_ERROR(0); OUTPUT: RETVAL int toFile( self, filename, format=0 ) xmlDocPtr self char * filename int format PREINIT: SV* internalFlag = NULL; int oldTagFlag = xmlSaveNoEmptyTags; PREINIT_SAVED_ERROR CODE: internalFlag = get_sv("XML::LibXML::setTagCompression", 0); if( internalFlag ) { xmlSaveNoEmptyTags = SvTRUE(internalFlag); } INIT_ERROR_HANDLER; if ( format <= 0 ) { xs_warn( "use no formated toFile!" ); RETVAL = xmlSaveFile( filename, self ); } else { int t_indent_var = xmlIndentTreeOutput; xmlIndentTreeOutput = 1; RETVAL =xmlSaveFormatFile( filename, self, format); xmlIndentTreeOutput = t_indent_var; } xmlSaveNoEmptyTags = oldTagFlag; CLEANUP_ERROR_HANDLER; REPORT_ERROR(0); if ( RETVAL > 0 ) RETVAL = 1; else XSRETURN_UNDEF; OUTPUT: RETVAL SV * toStringHTML(self) xmlDocPtr self ALIAS: XML::LibXML::Document::serialize_html = 1 PREINIT: xmlChar *result=NULL; int len = 0; PREINIT_SAVED_ERROR CODE: PERL_UNUSED_VAR(ix); xs_warn( "use no formated toString!" ); INIT_ERROR_HANDLER; htmlDocDumpMemory(self, &result, &len); CLEANUP_ERROR_HANDLER; REPORT_ERROR(0); if (result == NULL) { XSRETURN_UNDEF; } else { /* warn("%s, %d\n",result, len); */ RETVAL = newSVpvn((char *)result, (STRLEN)len); xmlFree(result); } OUTPUT: RETVAL const char * URI( self ) xmlDocPtr self ALIAS: XML::LibXML::Document::documentURI = 1 CODE: PERL_UNUSED_VAR(ix); RETVAL = (const char*)xmlStrdup(self->URL ); OUTPUT: RETVAL void setURI( self, new_URI ) xmlDocPtr self char * new_URI CODE: if (new_URI) { xmlFree((xmlChar*)self->URL ); self->URL = xmlStrdup((const xmlChar*)new_URI); } SV* createDocument( CLASS, version="1.0", encoding=NULL ) char * version char * encoding ALIAS: XML::LibXML::Document::new = 1 PREINIT: xmlDocPtr doc=NULL; CODE: PERL_UNUSED_VAR(ix); doc = xmlNewDoc((const xmlChar*)version); if (encoding && *encoding != 0) { doc->encoding = (const xmlChar*)xmlStrdup((const xmlChar*)encoding); } RETVAL = PmmNodeToSv(INT2PTR(xmlNodePtr,doc),NULL); OUTPUT: RETVAL SV* createInternalSubset( self, Pname, extID, sysID ) xmlDocPtr self SV * Pname SV * extID SV * sysID PREINIT: xmlDtdPtr dtd = NULL; xmlChar * name = NULL; xmlChar * externalID = NULL; xmlChar * systemID = NULL; CODE: name = Sv2C( Pname, NULL ); if ( name == NULL ) { XSRETURN_UNDEF; } externalID = Sv2C(extID, NULL); systemID = Sv2C(sysID, NULL); dtd = xmlCreateIntSubset( self, name, externalID, systemID ); xmlFree(externalID); xmlFree(systemID); xmlFree(name); if ( dtd ) { RETVAL = PmmNodeToSv( INT2PTR(xmlNodePtr,dtd), PmmPROXYNODE(self) ); } else { XSRETURN_UNDEF; } OUTPUT: RETVAL SV* createExternalSubset( self, Pname, extID, sysID ) xmlDocPtr self SV * Pname SV * extID SV * sysID PREINIT: xmlDtdPtr dtd = NULL; xmlChar * name = NULL; xmlChar * externalID = NULL; xmlChar * systemID = NULL; CODE: name = Sv2C( Pname, NULL ); if ( name == NULL ) { XSRETURN_UNDEF; } externalID = Sv2C(extID, NULL); systemID = Sv2C(sysID, NULL); dtd = xmlNewDtd( self, name, externalID, systemID ); xmlFree(externalID); xmlFree(systemID); xmlFree(name); if ( dtd ) { RETVAL = PmmNodeToSv( (xmlNodePtr)dtd, PmmPROXYNODE(self) ); } else { XSRETURN_UNDEF; } OUTPUT: RETVAL SV* createDTD( self, Pname, extID, sysID ) xmlDocPtr self SV * Pname SV * extID SV * sysID PREINIT: xmlDtdPtr dtd = NULL; xmlChar * name = NULL; xmlChar * externalID = NULL; xmlChar * systemID = NULL; CODE: name = Sv2C( Pname, NULL ); if ( name == NULL ) { XSRETURN_UNDEF; } externalID = Sv2C(extID, NULL); systemID = Sv2C(sysID, NULL); dtd = xmlNewDtd( NULL, name, externalID, systemID ); dtd->doc = self; xmlFree(externalID); xmlFree(systemID); xmlFree(name); if ( dtd ) { RETVAL = PmmNodeToSv( (xmlNodePtr)dtd, PmmPROXYNODE(self) ); } else { XSRETURN_UNDEF; } OUTPUT: RETVAL SV* createDocumentFragment( self ) xmlDocPtr self CODE: RETVAL = PmmNodeToSv(xmlNewDocFragment(self), PmmPROXYNODE(self)); OUTPUT: RETVAL SV* createElement( self, name ) xmlDocPtr self SV* name PREINIT: xmlNodePtr newNode; xmlChar * elname = NULL; ProxyNodePtr docfrag = NULL; CODE: elname = nodeSv2C( name , (xmlNodePtr) self); if ( !LibXML_test_node_name( elname ) ) { xmlFree( elname ); croak( "bad name" ); } newNode = xmlNewNode(NULL , elname); xmlFree(elname); if ( newNode != NULL ) { docfrag = PmmNewFragment( self ); newNode->doc = self; xmlAddChild(PmmNODE(docfrag), newNode); RETVAL = PmmNodeToSv(newNode,docfrag); } else { xs_warn( "no node created!" ); XSRETURN_UNDEF; } OUTPUT: RETVAL SV* createRawElement( self, name ) xmlDocPtr self SV* name PREINIT: xmlNodePtr newNode; xmlChar * elname = NULL; ProxyNodePtr docfrag = NULL; CODE: elname = nodeSv2C( name , (xmlNodePtr) self); if ( !elname || xmlStrlen(elname) <= 0 ) { xmlFree( elname ); croak( "bad name" ); } newNode = xmlNewDocNode(self,NULL , elname, NULL); xmlFree(elname); if ( newNode != NULL ) { docfrag = PmmNewFragment( self ); xmlAddChild(PmmNODE(docfrag), newNode); RETVAL = PmmNodeToSv(newNode,docfrag); } else { xs_warn( "no node created!" ); XSRETURN_UNDEF; } OUTPUT: RETVAL SV* createElementNS( self, nsURI, name ) xmlDocPtr self SV * nsURI SV * name PREINIT: xmlChar * ename = NULL; xmlChar * prefix = NULL; xmlChar * localname = NULL; xmlChar * eURI = NULL; xmlNsPtr ns = NULL; ProxyNodePtr docfrag = NULL; xmlNodePtr newNode = NULL; CODE: ename = nodeSv2C( name , (xmlNodePtr) self ); if ( !LibXML_test_node_name( ename ) ) { xmlFree( ename ); croak( "bad name" ); } eURI = Sv2C( nsURI , NULL ); if ( eURI != NULL && xmlStrlen(eURI)!=0 ){ localname = xmlSplitQName2(ename, &prefix); if ( localname == NULL ) { localname = xmlStrdup( ename ); } ns = xmlNewNs( NULL, eURI, prefix ); newNode = xmlNewDocNode( self, ns, localname, NULL ); newNode->nsDef = ns; xmlFree(localname); } else { xs_warn( " ordinary element " ); /* ordinary element */ localname = ename; newNode = xmlNewDocNode( self, NULL , localname, NULL ); } docfrag = PmmNewFragment( self ); xmlAddChild(PmmNODE(docfrag), newNode); RETVAL = PmmNodeToSv(newNode, docfrag); if ( prefix != NULL ) { xmlFree(prefix); } if ( eURI != NULL ) { xmlFree(eURI); } xmlFree(ename); OUTPUT: RETVAL SV* createRawElementNS( self, nsURI, name ) xmlDocPtr self SV * nsURI SV * name PREINIT: xmlChar * ename = NULL; xmlChar * prefix = NULL; xmlChar * localname = NULL; xmlChar * eURI = NULL; xmlNsPtr ns = NULL; ProxyNodePtr docfrag = NULL; xmlNodePtr newNode = NULL; CODE: ename = nodeSv2C( name , (xmlNodePtr) self ); if ( !LibXML_test_node_name( ename ) ) { xmlFree( ename ); croak( "bad name" ); } eURI = Sv2C( nsURI , NULL ); if ( eURI != NULL && xmlStrlen(eURI)!=0 ){ localname = xmlSplitQName2(ename, &prefix); if ( localname == NULL ) { localname = xmlStrdup( ename ); } newNode = xmlNewDocNode( self,NULL , localname, NULL ); ns = xmlSearchNsByHref( self, newNode, eURI ); if ( ns == NULL ) { /* create a new NS if the NS does not already exists */ ns = xmlNewNs(newNode, eURI , prefix ); } if ( ns == NULL ) { xmlFreeNode( newNode ); xmlFree(eURI); xmlFree(localname); if ( prefix != NULL ) { xmlFree(prefix); } xmlFree(ename); XSRETURN_UNDEF; } xmlFree(localname); } else { xs_warn( " ordinary element " ); /* ordinary element */ localname = ename; newNode = xmlNewDocNode( self, NULL , localname, NULL ); } xmlSetNs(newNode, ns); docfrag = PmmNewFragment( self ); xmlAddChild(PmmNODE(docfrag), newNode); RETVAL = PmmNodeToSv(newNode, docfrag); if ( prefix != NULL ) { xmlFree(prefix); } if ( eURI != NULL ) { xmlFree(eURI); } xmlFree(ename); OUTPUT: RETVAL SV * createTextNode( self, content ) xmlDocPtr self SV * content PREINIT: xmlNodePtr newNode; xmlChar * elname = NULL; ProxyNodePtr docfrag = NULL; CODE: elname = nodeSv2C( content , (xmlNodePtr) self ); if ( elname != NULL || xmlStrlen(elname) > 0 ) { newNode = xmlNewDocText( self, elname ); xmlFree(elname); if ( newNode != NULL ) { docfrag = PmmNewFragment( self ); newNode->doc = self; xmlAddChild(PmmNODE(docfrag), newNode); RETVAL = PmmNodeToSv(newNode,docfrag); } else { xs_warn( "no node created!" ); XSRETURN_UNDEF; } } else { XSRETURN_UNDEF; } OUTPUT: RETVAL SV * createComment( self , content ) xmlDocPtr self SV * content PREINIT: xmlNodePtr newNode; xmlChar * elname = NULL; ProxyNodePtr docfrag = NULL; CODE: elname = nodeSv2C( content , (xmlNodePtr) self ); if ( elname != NULL || xmlStrlen(elname) > 0 ) { newNode = xmlNewDocComment( self, elname ); xmlFree(elname); if ( newNode != NULL ) { docfrag = PmmNewFragment( self ); newNode->doc = self; xmlAddChild(PmmNODE(docfrag), newNode); xs_warn( newNode->name ); RETVAL = PmmNodeToSv(newNode,docfrag); } else { xs_warn( "no node created!" ); XSRETURN_UNDEF; } } else { XSRETURN_UNDEF; } OUTPUT: RETVAL SV * createCDATASection( self, content ) xmlDocPtr self SV * content PREINIT: xmlNodePtr newNode; xmlChar * elname = NULL; ProxyNodePtr docfrag = NULL; CODE: elname = nodeSv2C( content , (xmlNodePtr)self ); if ( elname != NULL || xmlStrlen(elname) > 0 ) { newNode = xmlNewCDataBlock( self, elname, xmlStrlen(elname) ); xmlFree(elname); if ( newNode != NULL ) { docfrag = PmmNewFragment( self ); newNode->doc = self; xmlAddChild(PmmNODE(docfrag), newNode); xs_warn( "[CDATA section]" ); RETVAL = PmmNodeToSv(newNode,docfrag); } else { xs_warn( "no node created!" ); XSRETURN_UNDEF; } } else { XSRETURN_UNDEF; } OUTPUT: RETVAL SV* createEntityReference( self , pname ) xmlDocPtr self SV * pname PREINIT: xmlNodePtr newNode; xmlChar * name = Sv2C( pname, NULL ); ProxyNodePtr docfrag = NULL; CODE: if ( name == NULL ) { XSRETURN_UNDEF; } newNode = xmlNewReference( self, name ); xmlFree(name); if ( newNode == NULL ) { XSRETURN_UNDEF; } docfrag = PmmNewFragment( self ); xmlAddChild(PmmNODE(docfrag), newNode); RETVAL = PmmNodeToSv( newNode, docfrag ); OUTPUT: RETVAL SV* createAttribute( self, pname, pvalue=&PL_sv_undef ) xmlDocPtr self SV * pname SV * pvalue PREINIT: xmlChar * name = NULL; xmlChar * value = NULL; xmlAttrPtr newAttr = NULL; xmlChar * buffer = NULL; CODE: name = nodeSv2C( pname , (xmlNodePtr) self ); if ( !LibXML_test_node_name( name ) ) { xmlFree(name); XSRETURN_UNDEF; } value = nodeSv2C( pvalue , (xmlNodePtr) self ); /* unlike xmlSetProp, xmlNewDocProp does not encode entities in value */ buffer = xmlEncodeEntitiesReentrant(self, value); newAttr = xmlNewDocProp( self, name, buffer ); RETVAL = PmmNodeToSv((xmlNodePtr)newAttr, PmmPROXYNODE(self)); xmlFree(name); xmlFree(buffer); if ( value ) { xmlFree(value); } OUTPUT: RETVAL SV* createAttributeNS( self, URI, pname, pvalue=&PL_sv_undef ) xmlDocPtr self SV * URI SV * pname SV * pvalue PREINIT: xmlChar * name = NULL; xmlChar * value = NULL; xmlChar * prefix = NULL; const xmlChar * pchar = NULL; xmlChar * localname = NULL; xmlChar * nsURI = NULL; xmlAttrPtr newAttr = NULL; xmlNsPtr ns = NULL; CODE: name = nodeSv2C( pname , (xmlNodePtr) self ); if ( !LibXML_test_node_name( name ) ) { xmlFree(name); XSRETURN_UNDEF; } nsURI = Sv2C( URI , NULL ); value = nodeSv2C( pvalue, (xmlNodePtr) self ); if ( nsURI != NULL && xmlStrlen(nsURI) > 0 ) { xmlNodePtr root = xmlDocGetRootElement(self ); if ( root ) { pchar = xmlStrchr(name, ':'); if ( pchar != NULL ) { localname = xmlSplitQName2(name, &prefix); } else { localname = xmlStrdup( name ); } ns = xmlSearchNsByHref( self, root, nsURI ); if ( ns == NULL ) { /* create a new NS if the NS does not already exists */ ns = xmlNewNs(root, nsURI , prefix ); } if ( ns == NULL ) { xmlFree(nsURI); xmlFree(localname); if ( prefix ) { xmlFree(prefix); } xmlFree(name); if ( value ) { xmlFree(value); } XSRETURN_UNDEF; } newAttr = xmlNewDocProp( self, localname, value ); xmlSetNs((xmlNodePtr)newAttr, ns); RETVAL = PmmNodeToSv((xmlNodePtr)newAttr, PmmPROXYNODE(self) ); xmlFree(nsURI); xmlFree(name); if ( prefix ) { xmlFree(prefix); } xmlFree(localname); if ( value ) { xmlFree(value); } } else { croak( "can't create a new namespace on an attribute!" ); xmlFree(name); if ( value ) { xmlFree(value); } XSRETURN_UNDEF; } } else { xmlChar *buffer; /* unlike xmlSetProp, xmlNewDocProp does not encode entities in value */ buffer = xmlEncodeEntitiesReentrant(self, value); newAttr = xmlNewDocProp( self, name, buffer ); RETVAL = PmmNodeToSv((xmlNodePtr)newAttr,PmmPROXYNODE(self)); xmlFree(name); xmlFree(buffer); if ( value ) { xmlFree(value); } } OUTPUT: RETVAL SV* createProcessingInstruction(self, name, value=&PL_sv_undef) xmlDocPtr self SV * name SV * value ALIAS: createPI = 1 PREINIT: xmlChar * n = NULL; xmlChar * v = NULL; xmlNodePtr newNode = NULL; ProxyNodePtr docfrag = NULL; CODE: PERL_UNUSED_VAR(ix); n = nodeSv2C(name, (xmlNodePtr)self); if ( !n ) { XSRETURN_UNDEF; } v = nodeSv2C(value, (xmlNodePtr)self); newNode = xmlNewPI(n,v); xmlFree(v); xmlFree(n); if ( newNode != NULL ) { docfrag = PmmNewFragment( self ); newNode->doc = self; xmlAddChild(PmmNODE(docfrag), newNode); RETVAL = PmmNodeToSv(newNode,docfrag); } else { xs_warn( "no node created!" ); XSRETURN_UNDEF; } OUTPUT: RETVAL void _setDocumentElement( self , proxy ) xmlDocPtr self SV * proxy PREINIT: xmlNodePtr elem, oelem; INIT: elem = PmmSvNode(proxy); if ( elem == NULL ) { XSRETURN_UNDEF; } CODE: /* please correct me if i am wrong: the document element HAS to be * an ELEMENT NODE */ if ( elem->type == XML_ELEMENT_NODE ) { if ( self != elem->doc ) { domImportNode( self, elem, 1, 1 ); } oelem = xmlDocGetRootElement( self ); if ( oelem == NULL || oelem->_private == NULL ) { xmlDocSetRootElement( self, elem ); } else { ProxyNodePtr docfrag = PmmNewFragment( self ); xmlReplaceNode( oelem, elem ); xmlAddChild( PmmNODE(docfrag), oelem ); PmmFixOwner( ((ProxyNodePtr)oelem->_private), docfrag); } if ( elem->_private != NULL ) { PmmFixOwner( SvPROXYNODE(proxy), PmmPROXYNODE(self)); } } else { croak("setDocumentElement: ELEMENT node required"); } SV * documentElement( self ) xmlDocPtr self ALIAS: XML::LibXML::Document::getDocumentElement = 1 PREINIT: xmlNodePtr elem; CODE: PERL_UNUSED_VAR(ix); elem = xmlDocGetRootElement( self ); if ( elem ) { RETVAL = PmmNodeToSv(elem, PmmPROXYNODE(self)); } else { XSRETURN_UNDEF; } OUTPUT: RETVAL SV * externalSubset( self ) xmlDocPtr self PREINIT: xmlDtdPtr dtd; CODE: if ( self->extSubset == NULL ) { XSRETURN_UNDEF; } dtd = self->extSubset; RETVAL = PmmNodeToSv((xmlNodePtr)dtd, PmmPROXYNODE(self)); OUTPUT: RETVAL SV * internalSubset( self ) xmlDocPtr self PREINIT: xmlDtdPtr dtd; CODE: if ( self->intSubset == NULL ) { XSRETURN_UNDEF; } dtd = self->intSubset; RETVAL = PmmNodeToSv(INT2PTR(xmlNodePtr,dtd), PmmPROXYNODE(self)); OUTPUT: RETVAL void setExternalSubset( self, extdtd ) xmlDocPtr self SV * extdtd PREINIT: xmlDtdPtr dtd = NULL; xmlDtdPtr olddtd = NULL; INIT: dtd = (xmlDtdPtr)PmmSvNode(extdtd); if ( dtd == NULL ) { croak( "lost DTD node" ); } CODE: if ( dtd && dtd != self->extSubset ) { if ( dtd->doc == NULL ) { xmlSetTreeDoc( (xmlNodePtr) dtd, self ); } else if ( dtd->doc != self ) { domImportNode( self, (xmlNodePtr) dtd,1,1); } if ( dtd == self->intSubset ) { xmlUnlinkNode( (xmlNodePtr)dtd ); self->intSubset = NULL; } olddtd = self->extSubset; if ( olddtd && olddtd->_private == NULL ) { xmlFreeDtd( olddtd ); } self->extSubset = dtd; } void setInternalSubset( self, extdtd ) xmlDocPtr self SV * extdtd PREINIT: xmlDtdPtr dtd = NULL; xmlDtdPtr olddtd = NULL; INIT: dtd = (xmlDtdPtr)PmmSvNode(extdtd); if ( dtd == NULL ) { croak( "lost DTD node" ); } CODE: if ( dtd && dtd != self->intSubset ) { if ( dtd->doc != self ) { croak( "can't import DTDs" ); domImportNode( self, (xmlNodePtr) dtd,1,1); } if ( dtd == self->extSubset ) { self->extSubset = NULL; } olddtd = xmlGetIntSubset( self ); if( olddtd ) { xmlReplaceNode( (xmlNodePtr)olddtd, (xmlNodePtr) dtd ); if ( olddtd->_private == NULL ) { xmlFreeDtd( olddtd ); } } else { if (self->children == NULL) xmlAddChild((xmlNodePtr) self, (xmlNodePtr) dtd); else xmlAddPrevSibling(self->children, (xmlNodePtr) dtd); } self->intSubset = dtd; } SV * removeInternalSubset( self ) xmlDocPtr self PREINIT: xmlDtdPtr dtd = NULL; CODE: dtd = xmlGetIntSubset(self); if ( !dtd ) { XSRETURN_UNDEF; } xmlUnlinkNode( (xmlNodePtr)dtd ); self->intSubset = NULL; RETVAL = PmmNodeToSv( (xmlNodePtr)dtd, PmmPROXYNODE(self) ); OUTPUT: RETVAL SV * removeExternalSubset( self ) xmlDocPtr self PREINIT: xmlDtdPtr dtd = NULL; CODE: dtd = self->extSubset; if ( !dtd ) { XSRETURN_UNDEF; } self->extSubset = NULL; RETVAL = PmmNodeToSv( (xmlNodePtr)dtd, PmmPROXYNODE(self) ); OUTPUT: RETVAL SV * importNode( self, node, dummy=0 ) xmlDocPtr self xmlNodePtr node int dummy PREINIT: xmlNodePtr ret = NULL; ProxyNodePtr docfrag = NULL; CODE: if ( node->type == XML_DOCUMENT_NODE || node->type == XML_HTML_DOCUMENT_NODE ) { croak( "Can't import Documents!" ); XSRETURN_UNDEF; } if (node->type == XML_DTD_NODE) { croak("Can't import DTD nodes"); } ret = domImportNode( self, node, 0, 1 ); if ( ret ) { docfrag = PmmNewFragment( self ); xmlAddChild( PmmNODE(docfrag), ret ); RETVAL = PmmNodeToSv( ret, docfrag); } else { XSRETURN_UNDEF; } OUTPUT: RETVAL SV * adoptNode( self, node ) xmlDocPtr self xmlNodePtr node PREINIT: xmlNodePtr ret = NULL; ProxyNodePtr docfrag = NULL; CODE: if ( node->type == XML_DOCUMENT_NODE || node->type == XML_HTML_DOCUMENT_NODE ) { croak( "Can't adopt Documents!" ); XSRETURN_UNDEF; } if (node->type == XML_DTD_NODE) { croak("Can't adopt DTD nodes"); } ret = domImportNode( self, node, 1, 1 ); if ( ret ) { docfrag = PmmNewFragment( self ); RETVAL = PmmNodeToSv(node, docfrag); xmlAddChild( PmmNODE(docfrag), ret ); PmmFixOwner(SvPROXYNODE(RETVAL), docfrag); } else { XSRETURN_UNDEF; } OUTPUT: RETVAL char* encoding( self ) xmlDocPtr self ALIAS: XML::LibXML::Document::getEncoding = 1 XML::LibXML::Document::xmlEncoding = 2 CODE: PERL_UNUSED_VAR(ix); RETVAL = (char *) self->encoding; OUTPUT: RETVAL void setEncoding( self, encoding = NULL ) xmlDocPtr self char *encoding PREINIT: int charset = XML_CHAR_ENCODING_ERROR; CODE: if ( self->encoding != NULL ) { xmlFree( (xmlChar*) self->encoding ); } if (encoding!=NULL && strlen(encoding)) { self->encoding = xmlStrdup( (const xmlChar *)encoding ); charset = (int)xmlParseCharEncoding( (const char*)self->encoding ); if ( charset <= 0 ) { charset = XML_CHAR_ENCODING_ERROR; } } else { self->encoding=NULL; charset = XML_CHAR_ENCODING_UTF8; } SetPmmNodeEncoding(self, charset); int standalone( self ) xmlDocPtr self ALIAS: XML::LibXML::Document::xmlStandalone = 1 CODE: PERL_UNUSED_VAR(ix); RETVAL = self->standalone; OUTPUT: RETVAL void setStandalone( self, value = 0 ) xmlDocPtr self int value CODE: if ( value > 0 ) { self->standalone = 1; } else if ( value < 0 ) { self->standalone = -1; } else { self->standalone = 0; } char* version( self ) xmlDocPtr self ALIAS: XML::LibXML::Document::getVersion = 1 XML::LibXML::Document::xmlVersion = 2 CODE: PERL_UNUSED_VAR(ix); RETVAL = (char *) self->version; OUTPUT: RETVAL void setVersion( self, version ) xmlDocPtr self char *version CODE: if ( self->version != NULL ) { xmlFree( (xmlChar*) self->version ); } self->version = xmlStrdup( (const xmlChar*)version ); int compression( self ) xmlDocPtr self CODE: RETVAL = xmlGetDocCompressMode(self); OUTPUT: RETVAL void setCompression( self, zLevel ) xmlDocPtr self int zLevel CODE: xmlSetDocCompressMode(self, zLevel); int is_valid(self, ...) xmlDocPtr self PREINIT: xmlValidCtxt cvp; xmlDtdPtr dtd = NULL; SV * dtd_sv; PREINIT_SAVED_ERROR CODE: INIT_ERROR_HANDLER; cvp.userData = saved_error; cvp.error = (xmlValidityErrorFunc)LibXML_validity_error_ctx; cvp.warning = (xmlValidityWarningFunc)LibXML_validity_warning_ctx; /* we need to initialize the node stack, because perl might * already have messed it up. */ cvp.nodeNr = 0; cvp.nodeTab = NULL; cvp.vstateNr = 0; cvp.vstateTab = NULL; PmmClearPSVI(self); PmmInvalidatePSVI(self); if (items > 1) { dtd_sv = ST(1); if ( sv_isobject(dtd_sv) && (SvTYPE(SvRV(dtd_sv)) == SVt_PVMG) ) { dtd = (xmlDtdPtr)PmmSvNode(dtd_sv); } RETVAL = xmlValidateDtd(&cvp, self, dtd); } else { RETVAL = xmlValidateDocument(&cvp, self); } CLEANUP_ERROR_HANDLER; /* REPORT_ERROR(1); */ OUTPUT: RETVAL int validate(self, ...) xmlDocPtr self PREINIT: xmlValidCtxt cvp; xmlDtdPtr dtd; SV * dtd_sv; PREINIT_SAVED_ERROR CODE: INIT_ERROR_HANDLER; cvp.userData = saved_error; cvp.error = (xmlValidityErrorFunc)LibXML_validity_error_ctx; cvp.warning = (xmlValidityWarningFunc)LibXML_validity_warning_ctx; /* we need to initialize the node stack, because perl might * already have messed it up. */ cvp.nodeNr = 0; cvp.nodeTab = NULL; cvp.vstateNr = 0; cvp.vstateTab = NULL; PmmClearPSVI(self); PmmInvalidatePSVI(self); if (items > 1) { dtd_sv = ST(1); if ( sv_isobject(dtd_sv) && (SvTYPE(SvRV(dtd_sv)) == SVt_PVMG) ) { dtd = (xmlDtdPtr)PmmSvNode(dtd_sv); } else { CLEANUP_ERROR_HANDLER; croak("is_valid: argument must be a DTD object"); } RETVAL = xmlValidateDtd(&cvp, self , dtd); } else { RETVAL = xmlValidateDocument(&cvp, self); } CLEANUP_ERROR_HANDLER; REPORT_ERROR(RETVAL ? 1 : 0); OUTPUT: RETVAL SV* cloneNode( self, deep=0 ) xmlDocPtr self int deep PREINIT: xmlDocPtr ret = NULL; CODE: ret = xmlCopyDoc( self, deep ); if ( ret == NULL ) { XSRETURN_UNDEF; } RETVAL = PmmNodeToSv((xmlNodePtr)ret, NULL); OUTPUT: RETVAL SV* getElementById( self, id ) xmlDocPtr self const char * id ALIAS: XML::LibXML::Document::getElementsById = 1 PREINIT: xmlNodePtr elem; xmlAttrPtr attr; CODE: PERL_UNUSED_VAR(ix); if ( id != NULL ) { attr = xmlGetID(self, (xmlChar *) id); if (attr == NULL) elem = NULL; else if (attr->type == XML_ATTRIBUTE_NODE) elem = attr->parent; else if (attr->type == XML_ELEMENT_NODE) elem = (xmlNodePtr) attr; else elem = NULL; if (elem != NULL) { RETVAL = PmmNodeToSv(elem, PmmPROXYNODE(self)); } else { XSRETURN_UNDEF; } } else { XSRETURN_UNDEF; } OUTPUT: RETVAL int indexElements ( self ) xmlDocPtr self CODE: #if LIBXML_VERSION >= 20508 RETVAL = xmlXPathOrderDocElems( self ); #else RETVAL = -2; #endif OUTPUT: RETVAL MODULE = XML::LibXML PACKAGE = XML::LibXML::Node void DESTROY( node ) SV * node PREINIT: int count; SV *is_shared; CODE: #ifdef XML_LIBXML_THREADS if ( (is_shared = get_sv("XML::LibXML::__threads_shared", 0)) == NULL ) { is_shared = &PL_sv_undef; } if ( SvTRUE(is_shared) ) { dSP; ENTER; SAVETMPS; PUSHMARK(SP); XPUSHs(node); PUTBACK; count = call_pv("threads::shared::is_shared", G_SCALAR); SPAGAIN; if (count != 1) croak("Couldn't checks if the variable is shared or not\n"); is_shared = POPs; PUTBACK; FREETMPS; LEAVE; if (is_shared != &PL_sv_undef) { XSRETURN_UNDEF; } } if( PmmUSEREGISTRY ) { SvLOCK(PROXY_NODE_REGISTRY_MUTEX); PmmRegistryREFCNT_dec(SvPROXYNODE(node)); } #endif PmmREFCNT_dec(SvPROXYNODE(node)); #ifdef XML_LIBXML_THREADS if( PmmUSEREGISTRY ) SvUNLOCK(PROXY_NODE_REGISTRY_MUTEX); #endif SV* nodeName( self ) xmlNodePtr self ALIAS: XML::LibXML::Node::getName = 1 XML::LibXML::Element::tagName = 2 PREINIT: xmlChar * name = NULL; CODE: PERL_UNUSED_VAR(ix); name = (xmlChar*)domName( self ); if ( name != NULL ) { RETVAL = C2Sv(name,NULL); xmlFree( name ); } else { XSRETURN_UNDEF; } OUTPUT: RETVAL SV* localname( self ) xmlNodePtr self ALIAS: XML::LibXML::Node::getLocalName = 1 XML::LibXML::Attr::name = 2 XML::LibXML::Node::localName = 3 CODE: PERL_UNUSED_VAR(ix); if ( self->type == XML_ELEMENT_NODE || self->type == XML_ATTRIBUTE_NODE || self->type == XML_ELEMENT_DECL || self->type == XML_ATTRIBUTE_DECL ) { RETVAL = C2Sv(self->name,NULL); } else { XSRETURN_UNDEF; } OUTPUT: RETVAL SV* prefix( self ) xmlNodePtr self ALIAS: XML::LibXML::Node::getPrefix = 1 CODE: PERL_UNUSED_VAR(ix); if( ( self->type == XML_ELEMENT_NODE || self->type == XML_ATTRIBUTE_NODE || self->type == XML_PI_NODE ) && self->ns != NULL && self->ns->prefix != NULL ) { RETVAL = C2Sv(self->ns->prefix, NULL); } else { XSRETURN_UNDEF; } OUTPUT: RETVAL SV* namespaceURI( self ) xmlNodePtr self ALIAS: getNamespaceURI = 1 PREINIT: xmlChar * nsURI; CODE: PERL_UNUSED_VAR(ix); if ( ( self->type == XML_ELEMENT_NODE || self->type == XML_ATTRIBUTE_NODE || self->type == XML_PI_NODE ) && self->ns != NULL && self->ns->href != NULL ) { nsURI = xmlStrdup(self->ns->href); RETVAL = C2Sv( nsURI, NULL ); xmlFree( nsURI ); } else { XSRETURN_UNDEF; } OUTPUT: RETVAL SV* lookupNamespaceURI( self, svprefix=&PL_sv_undef ) xmlNodePtr self SV * svprefix PREINIT: xmlChar * nsURI; xmlChar * prefix = NULL; xmlNsPtr ns; CODE: prefix = nodeSv2C( svprefix , self ); if ( prefix != NULL && xmlStrlen(prefix) == 0) { xmlFree( prefix ); prefix = NULL; } ns = xmlSearchNs( self->doc, self, prefix ); if ( prefix != NULL) { xmlFree( prefix ); } if ( ns != NULL ) { nsURI = xmlStrdup(ns->href); RETVAL = C2Sv( nsURI, NULL ); xmlFree( nsURI ); } else { XSRETURN_UNDEF; } OUTPUT: RETVAL SV* lookupNamespacePrefix( self, svuri ) xmlNodePtr self SV * svuri PREINIT: xmlChar * nsprefix; xmlChar * href = NULL; CODE: href = nodeSv2C( svuri , self ); if ( href != NULL && xmlStrlen(href) > 0) { xmlNsPtr ns = xmlSearchNsByHref( self->doc, self, href ); xmlFree( href ); if ( ns != NULL ) { if ( ns->prefix != NULL ) { nsprefix = xmlStrdup( ns->prefix ); RETVAL = C2Sv( nsprefix, NULL ); xmlFree(nsprefix); } else { RETVAL = newSVpv("",0); } } else { XSRETURN_UNDEF; } } else { XSRETURN_UNDEF; } OUTPUT: RETVAL void setNodeName( self , value ) xmlNodePtr self SV* value ALIAS: setName = 1 PREINIT: xmlChar* string; xmlChar* localname; xmlChar* prefix; CODE: PERL_UNUSED_VAR(ix); string = nodeSv2C( value , self ); if ( !LibXML_test_node_name( string ) ) { xmlFree(string); croak( "bad name" ); } if( ( self->type == XML_ELEMENT_NODE || self->type == XML_ATTRIBUTE_NODE || self->type == XML_PI_NODE) && self->ns ){ localname = xmlSplitQName2(string, &prefix); if ( localname == NULL ) { localname = xmlStrdup( string ); } xmlNodeSetName(self, localname ); xmlFree(localname); xmlFree(prefix); } else { xs_warn("node name normal\n"); xmlNodeSetName(self, string ); } xmlFree(string); void setRawName( self, value ) xmlNodePtr self SV * value PREINIT: xmlChar* string; xmlChar* localname; xmlChar* prefix; CODE: string = nodeSv2C( value , self ); if ( !string || xmlStrlen( string) <= 0 ) { xmlFree(string); XSRETURN_UNDEF; } if( ( self->type == XML_ELEMENT_NODE || self->type == XML_ATTRIBUTE_NODE || self->type == XML_PI_NODE) && self->ns ){ localname = xmlSplitQName2(string, &prefix); xmlNodeSetName(self, localname ); xmlFree(localname); xmlFree(prefix); } else { xmlNodeSetName(self, string ); } xmlFree(string); SV* nodeValue( self, useDomEncoding = &PL_sv_undef ) xmlNodePtr self SV * useDomEncoding ALIAS: XML::LibXML::Attr::value = 1 XML::LibXML::Attr::getValue = 2 XML::LibXML::Text::data = 3 XML::LibXML::Node::getValue = 4 XML::LibXML::Node::getData = 5 PREINIT: xmlChar * content = NULL; CODE: PERL_UNUSED_VAR(ix); content = domGetNodeValue( self ); if ( content != NULL ) { if ( SvTRUE(useDomEncoding) ) { RETVAL = nodeC2Sv(content, self); } else { RETVAL = C2Sv(content, NULL); } xmlFree(content); } else { XSRETURN_UNDEF; } OUTPUT: RETVAL int nodeType( self ) xmlNodePtr self ALIAS: XML::LibXML::Node::getType = 1 CODE: PERL_UNUSED_VAR(ix); RETVAL = self->type; OUTPUT: RETVAL SV* parentNode( self ) xmlNodePtr self ALIAS: XML::LibXML::Attr::ownerElement = 1 XML::LibXML::Node::getParentNode = 2 XML::LibXML::Attr::getOwnerElement = 3 CODE: PERL_UNUSED_VAR(ix); RETVAL = PmmNodeToSv( self->parent, PmmOWNERPO( PmmPROXYNODE(self) ) ); OUTPUT: RETVAL SV* nextSibling( self ) xmlNodePtr self ALIAS: getNextSibling = 1 CODE: PERL_UNUSED_VAR(ix); RETVAL = PmmNodeToSv( self->next, PmmOWNERPO(PmmPROXYNODE(self)) ); OUTPUT: RETVAL SV* nextNonBlankSibling( self ) xmlNodePtr self PREINIT: xmlNodePtr next; CODE: next = self->next; while (next != NULL && xmlIsBlankNode(next)) next = next->next; RETVAL = PmmNodeToSv( next, PmmOWNERPO(PmmPROXYNODE(self)) ); OUTPUT: RETVAL SV* previousSibling( self ) xmlNodePtr self ALIAS: getPreviousSibling = 1 CODE: PERL_UNUSED_VAR(ix); RETVAL = PmmNodeToSv( self->prev, PmmOWNERPO( PmmPROXYNODE(self) ) ); OUTPUT: RETVAL SV* previousNonBlankSibling( self ) xmlNodePtr self PREINIT: xmlNodePtr prev; CODE: prev = self->prev; while (prev != NULL && xmlIsBlankNode(prev)) prev = prev->prev; RETVAL = PmmNodeToSv( prev, PmmOWNERPO(PmmPROXYNODE(self)) ); OUTPUT: RETVAL void _childNodes( self, only_nonblank = 0 ) xmlNodePtr self int only_nonblank ALIAS: XML::LibXML::Node::getChildnodes = 1 PREINIT: xmlNodePtr cld; SV * element; int len = 0; int wantarray = GIMME_V; PPCODE: PERL_UNUSED_VAR(ix); if ( self->type != XML_ATTRIBUTE_NODE ) { cld = self->children; xs_warn("childnodes start"); while ( cld ) { if ( !(only_nonblank && xmlIsBlankNode(cld)) ) { if( wantarray != G_SCALAR ) { element = PmmNodeToSv(cld, PmmOWNERPO(PmmPROXYNODE(self)) ); XPUSHs(sv_2mortal(element)); } len++; } cld = cld->next; } } if ( wantarray == G_SCALAR ) { XPUSHs(sv_2mortal(newSViv(len)) ); } void _getChildrenByTagNameNS( self, namespaceURI, node_name ) xmlNodePtr self SV * namespaceURI SV * node_name PREINIT: xmlChar * name; xmlChar * nsURI; xmlNodePtr cld; SV * element; int len = 0; int name_wildcard = 0; int ns_wildcard = 0; int wantarray = GIMME_V; PPCODE: name = nodeSv2C(node_name, self ); nsURI = nodeSv2C(namespaceURI, self ); if ( nsURI != NULL ) { if (xmlStrlen(nsURI) == 0 ) { xmlFree(nsURI); nsURI = NULL; } else if (xmlStrcmp( nsURI, (xmlChar *)"*" )==0) { ns_wildcard = 1; } } if ( name !=NULL && xmlStrcmp( name, (xmlChar *)"*" ) == 0) { name_wildcard = 1; } if ( self->type != XML_ATTRIBUTE_NODE ) { cld = self->children; xs_warn("childnodes start"); while ( cld ) { if (((name_wildcard && (cld->type == XML_ELEMENT_NODE)) || xmlStrcmp( name, cld->name ) == 0) && (ns_wildcard || (cld->ns != NULL && xmlStrcmp(nsURI,cld->ns->href) == 0 ) || (cld->ns == NULL && nsURI == NULL))) { if( wantarray != G_SCALAR ) { element = PmmNodeToSv(cld, PmmOWNERPO(PmmPROXYNODE(self)) ); XPUSHs(sv_2mortal(element)); } len++; } cld = cld->next; } } if ( wantarray == G_SCALAR ) { XPUSHs(sv_2mortal(newSViv(len)) ); } xmlFree(name); if (nsURI) xmlFree(nsURI); SV* firstChild( self ) xmlNodePtr self ALIAS: getFirstChild = 1 CODE: PERL_UNUSED_VAR(ix); RETVAL = PmmNodeToSv( self->children, PmmOWNERPO( PmmPROXYNODE(self) ) ); OUTPUT: RETVAL SV* firstNonBlankChild( self ) xmlNodePtr self PREINIT: xmlNodePtr child; CODE: child = self->children; while (child !=NULL && xmlIsBlankNode(child)) child = child->next; RETVAL = PmmNodeToSv( child, PmmOWNERPO( PmmPROXYNODE(self) ) ); OUTPUT: RETVAL SV* lastChild( self ) xmlNodePtr self ALIAS: getLastChild = 1 CODE: PERL_UNUSED_VAR(ix); RETVAL = PmmNodeToSv( self->last, PmmOWNERPO( PmmPROXYNODE(self) ) ); OUTPUT: RETVAL void _attributes( self ) xmlNodePtr self ALIAS: XML::LibXML::Node::getAttributes = 1 PREINIT: xmlAttrPtr attr = NULL; xmlNsPtr ns = NULL; SV * element; int len=0; int wantarray = GIMME_V; PPCODE: PERL_UNUSED_VAR(ix); if ( self->type != XML_ATTRIBUTE_NODE && self->type != XML_DTD_NODE ) { attr = self->properties; while ( attr != NULL ) { if ( wantarray != G_SCALAR ) { element = PmmNodeToSv((xmlNodePtr)attr, PmmOWNERPO(PmmPROXYNODE(self)) ); XPUSHs(sv_2mortal(element)); } attr = attr->next; len++; } if (self->type == XML_ELEMENT_NODE) { ns = self->nsDef; while ( ns != NULL ) { const char * CLASS = "XML::LibXML::Namespace"; if ( wantarray != G_SCALAR ) { /* namespace handling is kinda odd: * as soon we have a namespace isolated from its * owner, we loose the context. therefore it is * forbidden to access the NS information directly. * instead the use will receive a copy of the real * namespace, that can be destroied and is not * bound to a document. * * this avoids segfaults in the end. */ if ((ns->prefix != NULL || ns->href != NULL)) { xmlNsPtr tns = xmlCopyNamespace(ns); if ( tns != NULL ) { element = sv_newmortal(); XPUSHs(sv_setref_pv( element, (char *)CLASS, (void*)tns)); } } } ns = ns->next; len++; } } } if( wantarray == G_SCALAR ) { XPUSHs( sv_2mortal(newSViv(len)) ); } int hasChildNodes( self ) xmlNodePtr self CODE: if ( self->type == XML_ATTRIBUTE_NODE ) { RETVAL = 0; } else { RETVAL = self->children ? 1 : 0 ; } OUTPUT: RETVAL int hasAttributes( self ) xmlNodePtr self CODE: if ( self->type == XML_ATTRIBUTE_NODE || self->type == XML_DTD_NODE ) { RETVAL = 0; } else { RETVAL = self->properties ? 1 : 0 ; } OUTPUT: RETVAL SV* ownerDocument( self ) xmlNodePtr self ALIAS: XML::LibXML::Node::getOwnerDocument = 1 CODE: PERL_UNUSED_VAR(ix); xs_warn( "GET OWNERDOC\n" ); if( self != NULL && self->doc != NULL ){ RETVAL = PmmNodeToSv((xmlNodePtr)(self->doc), NULL); } else { XSRETURN_UNDEF; } OUTPUT: RETVAL SV* ownerNode( self ) xmlNodePtr self ALIAS: XML::LibXML::Node::getOwner = 1 XML::LibXML::Node::getOwnerElement = 2 CODE: PERL_UNUSED_VAR(ix); RETVAL = PmmNodeToSv(PmmNODE(PmmOWNERPO(PmmPROXYNODE(self))), NULL); OUTPUT: RETVAL void normalize( self ) xmlNodePtr self CODE: domNodeNormalize( self ); SV* insertBefore( self, nNode, refNode ) xmlNodePtr self xmlNodePtr nNode SV * refNode PREINIT: xmlNodePtr oNode=NULL, rNode; INIT: oNode = PmmSvNode(refNode); CODE: rNode = domInsertBefore( self, nNode, oNode ); if ( rNode != NULL ) { RETVAL = PmmNodeToSv( rNode, PmmOWNERPO(PmmPROXYNODE(self)) ); if (rNode->type == XML_DTD_NODE) { LibXML_set_int_subset(self->doc, rNode); } PmmFixOwner(PmmPROXYNODE(rNode), PmmOWNERPO(PmmPROXYNODE(self))); } else { XSRETURN_UNDEF; } OUTPUT: RETVAL SV* insertAfter( self, nNode, refNode ) xmlNodePtr self xmlNodePtr nNode SV* refNode PREINIT: xmlNodePtr oNode = NULL, rNode; INIT: oNode = PmmSvNode(refNode); CODE: rNode = domInsertAfter( self, nNode, oNode ); if ( rNode != NULL ) { RETVAL = PmmNodeToSv( rNode, PmmOWNERPO(PmmPROXYNODE(self)) ); if (rNode->type == XML_DTD_NODE) { LibXML_set_int_subset(self->doc, rNode); } PmmFixOwner(PmmPROXYNODE(rNode), PmmOWNERPO(PmmPROXYNODE(self))); } else { XSRETURN_UNDEF; } OUTPUT: RETVAL SV* replaceChild( self, nNode, oNode ) xmlNodePtr self xmlNodePtr nNode xmlNodePtr oNode PREINIT: xmlNodePtr ret = NULL; CODE: // if newNode == oldNode or self == newNode then do nothing, just return nNode. if (nNode == oNode || self == nNode ) { ret = nNode; RETVAL = PmmNodeToSv(ret, PmmOWNERPO(PmmPROXYNODE(ret))); } else{ if ( self->type == XML_DOCUMENT_NODE ) { switch ( nNode->type ) { case XML_ELEMENT_NODE: warn("replaceChild with an element on a document node not supported yet!"); XSRETURN_UNDEF; break; case XML_DOCUMENT_FRAG_NODE: warn("replaceChild with a document fragment node on a document node not supported yet!"); XSRETURN_UNDEF; break; case XML_TEXT_NODE: case XML_CDATA_SECTION_NODE: warn("replaceChild with a text node not supported on a document node!"); XSRETURN_UNDEF; break; default: break; } } ret = domReplaceChild( self, nNode, oNode ); if (ret == NULL) { XSRETURN_UNDEF; } else { LibXML_reparent_removed_node(ret); RETVAL = PmmNodeToSv(ret, PmmOWNERPO(PmmPROXYNODE(ret))); if (nNode->type == XML_DTD_NODE) { LibXML_set_int_subset(nNode->doc, nNode); } if ( nNode->_private != NULL ) { PmmFixOwner( PmmPROXYNODE(nNode), PmmOWNERPO(PmmPROXYNODE(self)) ); } } } OUTPUT: RETVAL SV* replaceNode( self,nNode ) xmlNodePtr self xmlNodePtr nNode PREINIT: xmlNodePtr ret = NULL; ProxyNodePtr owner = NULL; CODE: if ( domIsParent( self, nNode ) == 1 ) { XSRETURN_UNDEF; } owner = PmmOWNERPO(PmmPROXYNODE(self)); if ( self->type != XML_ATTRIBUTE_NODE ) { ret = domReplaceChild( self->parent, nNode, self); } else { ret = xmlReplaceNode( self, nNode ); } if ( ret ) { LibXML_reparent_removed_node(ret); RETVAL = PmmNodeToSv(ret, PmmOWNERPO(PmmPROXYNODE(ret))); if (nNode->type == XML_DTD_NODE) { LibXML_set_int_subset(nNode->doc, nNode); } if ( nNode->_private != NULL ) { PmmFixOwner(PmmPROXYNODE(nNode), owner); } } else { croak( "replacement failed" ); XSRETURN_UNDEF; } OUTPUT: RETVAL SV* removeChild( self, node ) xmlNodePtr self xmlNodePtr node PREINIT: xmlNodePtr ret; CODE: ret = domRemoveChild( self, node ); if (ret == NULL) { XSRETURN_UNDEF; } else { LibXML_reparent_removed_node(ret); RETVAL = PmmNodeToSv(ret, NULL); } OUTPUT: RETVAL void removeChildNodes( self ) xmlNodePtr self PREINIT: xmlNodePtr elem, fragment; ProxyNodePtr docfrag; CODE: docfrag = PmmNewFragment( self->doc ); fragment = PmmNODE( docfrag ); elem = self->children; while ( elem ) { xmlNodePtr next = elem->next; xmlUnlinkNode( elem ); if (elem->type == XML_ATTRIBUTE_NODE || elem->type == XML_DTD_NODE) { if (PmmPROXYNODE(elem) == NULL) { xmlFreeNode(elem); } } else { /* this following piece is the function of domAppendChild() * but in this special case we can avoid most of the logic of * that function. */ if ( fragment->children != NULL ) { xs_warn("unlink node!\n"); domAddNodeToList( elem, fragment->last, NULL ); } else { fragment->children = elem; fragment->last = elem; elem->parent= fragment; } PmmFixOwnerNode( elem, docfrag ); } elem = next; } self->children = self->last = NULL; if ( PmmREFCNT(docfrag) <= 0 ) { xs_warn( "have not references left" ); PmmREFCNT_inc( docfrag ); PmmREFCNT_dec( docfrag ); } void unbindNode( self ) xmlNodePtr self ALIAS: XML::LibXML::Node::unlink = 1 XML::LibXML::Node::unlinkNode = 2 PREINIT: ProxyNodePtr docfrag = NULL; CODE: PERL_UNUSED_VAR(ix); if ( self->type != XML_DOCUMENT_NODE && self->type != XML_DOCUMENT_FRAG_NODE ) { xmlUnlinkNode( self ); LibXML_reparent_removed_node(self); } SV* appendChild( self, nNode ) xmlNodePtr self xmlNodePtr nNode PREINIT: xmlNodePtr rNode; CODE: if (self->type == XML_DOCUMENT_NODE ) { /* NOT_SUPPORTED_ERR */ switch ( nNode->type ) { case XML_ELEMENT_NODE: warn("Appending an element to a document node not supported yet!"); XSRETURN_UNDEF; break; case XML_DOCUMENT_FRAG_NODE: warn("Appending a document fragment node to a document node not supported yet!"); XSRETURN_UNDEF; break; case XML_TEXT_NODE: case XML_CDATA_SECTION_NODE: warn("Appending text node not supported on a document node yet!"); XSRETURN_UNDEF; break; default: break; } } rNode = domAppendChild( self, nNode ); if ( rNode == NULL ) { XSRETURN_UNDEF; } RETVAL = PmmNodeToSv( nNode, PmmOWNERPO(PmmPROXYNODE(self)) ); if (nNode->type == XML_DTD_NODE) { LibXML_set_int_subset(self->doc, nNode); } PmmFixOwner( SvPROXYNODE(RETVAL), PmmPROXYNODE(self) ); OUTPUT: RETVAL SV* addChild( self, nNode ) xmlNodePtr self xmlNodePtr nNode PREINIT: xmlNodePtr retval = NULL; ProxyNodePtr proxy; CODE: switch ( nNode->type ) { case XML_DOCUMENT_FRAG_NODE: croak("Adding document fragments with addChild not supported!"); XSRETURN_UNDEF; case XML_DOCUMENT_NODE : case XML_HTML_DOCUMENT_NODE : case XML_DOCB_DOCUMENT_NODE : croak("addChild: HIERARCHY_REQUEST_ERR\n"); XSRETURN_UNDEF; case XML_NOTATION_NODE : case XML_NAMESPACE_DECL : case XML_DTD_NODE : case XML_DOCUMENT_TYPE_NODE : case XML_ENTITY_DECL : case XML_ELEMENT_DECL : case XML_ATTRIBUTE_DECL : croak("addChild: unsupported node type!"); XSRETURN_UNDEF; default: break; } xmlUnlinkNode(nNode); proxy = PmmPROXYNODE(nNode); retval = xmlAddChild( self, nNode ); if ( retval == NULL ) { croak( "Error: addChild failed (check node types)!\n" ); } if ( retval != nNode ) { xs_warn( "node was lost during operation\n" ); PmmNODE(proxy) = NULL; } RETVAL = PmmNodeToSv( retval, PmmOWNERPO(PmmPROXYNODE(self)) ); if ( retval != self ) { PmmFixOwner( SvPROXYNODE(RETVAL), PmmPROXYNODE(self) ); } OUTPUT: RETVAL SV* addSibling( self, nNode ) xmlNodePtr self xmlNodePtr nNode PREINIT: xmlNodePtr ret = NULL; ProxyNodePtr owner = NULL; CODE: if ( nNode->type == XML_DOCUMENT_FRAG_NODE ) { croak("Adding document fragments with addSibling not yet supported!"); XSRETURN_UNDEF; } owner = PmmOWNERPO(PmmPROXYNODE(self)); if (self->type == XML_TEXT_NODE && nNode->type == XML_TEXT_NODE && self->name == nNode->name) { /* As a result of text merging, the added node may be freed. */ xmlNodePtr copy = xmlCopyNode(nNode, 0); ret = xmlAddSibling(self, copy); if (ret) { RETVAL = PmmNodeToSv(ret, owner); /* Unlink original node. */ xmlUnlinkNode(nNode); LibXML_reparent_removed_node(nNode); } else { xmlFreeNode(copy); XSRETURN_UNDEF; } } else { ret = xmlAddSibling( self, nNode ); if ( ret ) { RETVAL = PmmNodeToSv(ret, owner); if (nNode->type == XML_DTD_NODE) { LibXML_set_int_subset(self->doc, nNode); } PmmFixOwner(SvPROXYNODE(RETVAL), owner); } else { XSRETURN_UNDEF; } } OUTPUT: RETVAL SV* cloneNode( self, deep=0 ) xmlNodePtr self int deep PREINIT: xmlNodePtr ret; xmlDocPtr doc = NULL; ProxyNodePtr docfrag = NULL; CODE: ret = PmmCloneNode( self, deep ); if ( ret == NULL ) { XSRETURN_UNDEF; } if ( ret->type == XML_DTD_NODE ) { RETVAL = PmmNodeToSv(ret, NULL); } else { doc = self->doc; if ( doc != NULL ) { xmlSetTreeDoc(ret, doc); /* setting to self, no need to clear psvi */ } docfrag = PmmNewFragment( doc ); xmlAddChild( PmmNODE(docfrag), ret ); RETVAL = PmmNodeToSv(ret, docfrag); } OUTPUT: RETVAL int isSameNode( self, oNode ) xmlNodePtr self xmlNodePtr oNode ALIAS: XML::LibXML::Node::isEqual = 1 CODE: PERL_UNUSED_VAR(ix); RETVAL = ( self == oNode ) ? 1 : 0; OUTPUT: RETVAL IV unique_key( self ) xmlNodePtr self CODE: /* Cast pointer to IV */ RETVAL = PTR2IV(self); OUTPUT: RETVAL SV * baseURI( self ) xmlNodePtr self PREINIT: xmlChar * uri; CODE: uri = xmlNodeGetBase( self->doc, self ); RETVAL = C2Sv( uri, NULL ); xmlFree( uri ); OUTPUT: RETVAL void setBaseURI( self, URI ) xmlNodePtr self SV * URI PREINIT: xmlChar * uri; CODE: uri = nodeSv2C( URI, self ); if ( uri != NULL ) { xmlNodeSetBase( self, uri ); } SV* toString( self, format=0, useDomEncoding = &PL_sv_undef ) xmlNodePtr self SV * useDomEncoding int format ALIAS: XML::LibXML::Node::serialize = 1 PREINIT: xmlBufferPtr buffer; const xmlChar *ret = NULL; SV* internalFlag = NULL; int oldTagFlag = xmlSaveNoEmptyTags; CODE: PERL_UNUSED_VAR(ix); internalFlag = get_sv("XML::LibXML::setTagCompression", 0); if ( internalFlag ) { xmlSaveNoEmptyTags = SvTRUE(internalFlag); } buffer = xmlBufferCreate(); if ( format <= 0 ) { xmlNodeDump( buffer, self->doc, self, 0, format); } else { int t_indent_var = xmlIndentTreeOutput; xmlIndentTreeOutput = 1; xmlNodeDump( buffer, self->doc, self, 0, format); xmlIndentTreeOutput = t_indent_var; } ret = xmlBufferContent( buffer ); xmlSaveNoEmptyTags = oldTagFlag; if ( ret != NULL ) { if ( useDomEncoding != &PL_sv_undef && SvTRUE(useDomEncoding) ) { RETVAL = nodeC2Sv((xmlChar*)ret, PmmNODE(PmmPROXYNODE(self))) ; SvUTF8_off(RETVAL); } else { RETVAL = C2Sv((xmlChar*)ret, NULL) ; } xmlBufferFree( buffer ); } else { xmlBufferFree( buffer ); xs_warn("Failed to convert node to string"); XSRETURN_UNDEF; } OUTPUT: RETVAL SV * _toStringC14N(self, comments=0, xpath=&PL_sv_undef, exclusive=0, inc_prefix_list=NULL, xpath_context) xmlNodePtr self int comments SV * xpath int exclusive char** inc_prefix_list SV * xpath_context PREINIT: xmlChar *result = NULL; xmlChar *nodepath = NULL; xmlXPathContextPtr child_ctxt = NULL; xmlXPathObjectPtr xpath_res = NULL; xmlNodeSetPtr nodelist = NULL; xmlNodePtr refNode = NULL; PREINIT_SAVED_ERROR INIT: /* due to how c14n is implemented, the nodeset it receives must include child nodes; ie, child nodes aren't assumed to be rendered. so we use an xpath expression to find all of the child nodes. */ if ( self->doc == NULL ) { croak("Node passed to toStringC14N must be part of a document"); } refNode = self; CODE: if ( xpath != NULL && xpath != &PL_sv_undef ) { nodepath = Sv2C( xpath, NULL ); } if ( nodepath != NULL && xmlStrlen( nodepath ) == 0 ) { xmlFree( nodepath ); nodepath = NULL; } if ( nodepath == NULL && self->type != XML_DOCUMENT_NODE && self->type != XML_HTML_DOCUMENT_NODE && self->type != XML_DOCB_DOCUMENT_NODE ) { if (comments) nodepath = xmlStrdup( (const xmlChar *) "(. | .//node() | .//@* | .//namespace::*)" ); else nodepath = xmlStrdup( (const xmlChar *) "(. | .//node() | .//@* | .//namespace::*)[not(self::comment())]" ); } if ( nodepath != NULL ) { if ( self->type == XML_DOCUMENT_NODE || self->type == XML_HTML_DOCUMENT_NODE || self->type == XML_DOCB_DOCUMENT_NODE ) { refNode = xmlDocGetRootElement( self->doc ); } if (SvOK(xpath_context)) { child_ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(xpath_context))); if ( child_ctxt == NULL ) { croak("XPathContext: missing xpath context\n"); } } else { xpath_context = NULL; child_ctxt = xmlXPathNewContext(self->doc); } if (!child_ctxt) { if ( nodepath != NULL ) { xmlFree( nodepath ); } croak("Failed to create xpath context"); } child_ctxt->node = self; LibXML_configure_namespaces(child_ctxt); xpath_res = xmlXPathEval(nodepath, child_ctxt); if (child_ctxt->namespaces != NULL) { xmlFree( child_ctxt->namespaces ); child_ctxt->namespaces = NULL; } if (!xpath_context) xmlXPathFreeContext(child_ctxt); if ( nodepath != NULL ) { xmlFree( nodepath ); } if (xpath_res == NULL) { croak("2 Failed to compile xpath expression"); } nodelist = xpath_res->nodesetval; if ( nodelist == NULL ) { xmlXPathFreeObject(xpath_res); croak( "cannot canonize empty nodeset!" ); } } INIT_ERROR_HANDLER; xmlC14NDocDumpMemory( self->doc, nodelist, exclusive, (xmlChar **) inc_prefix_list, comments, &result ); if ( xpath_res ) xmlXPathFreeObject(xpath_res); CLEANUP_ERROR_HANDLER; REPORT_ERROR(0); if (result == NULL) { croak("Failed to convert doc to string in doc->toStringC14N"); } else { RETVAL = C2Sv( result, NULL ); xmlFree(result); } OUTPUT: RETVAL SV* string_value ( self, useDomEncoding = &PL_sv_undef ) xmlNodePtr self SV * useDomEncoding ALIAS: to_literal = 1 textContent = 2 PREINIT: xmlChar * string = NULL; CODE: PERL_UNUSED_VAR(ix); /* we can't just return a string, because of UTF8! */ string = xmlXPathCastNodeToString(self); if ( SvTRUE(useDomEncoding) ) { RETVAL = nodeC2Sv(string, self); } else { RETVAL = C2Sv(string, NULL); } xmlFree(string); OUTPUT: RETVAL double to_number ( self ) xmlNodePtr self CODE: RETVAL = xmlXPathCastNodeToNumber(self); OUTPUT: RETVAL void _find( pnode, pxpath, to_bool ) SV* pnode SV * pxpath int to_bool PREINIT: xmlNodePtr node = PmmSvNode(pnode); ProxyNodePtr owner = NULL; xmlXPathObjectPtr found = NULL; xmlNodeSetPtr nodelist = NULL; xmlChar * xpath = NULL; xmlXPathCompExprPtr comp = NULL; PREINIT_SAVED_ERROR INIT: if ( node == NULL ) { croak( "lost node" ); } if (sv_isobject(pxpath) && sv_isa(pxpath,"XML::LibXML::XPathExpression")) { comp = INT2PTR(xmlXPathCompExprPtr,SvIV((SV*)SvRV( pxpath ))); if (!comp) XSRETURN_UNDEF; } else { xpath = nodeSv2C(pxpath, node); if ( !(xpath && xmlStrlen(xpath)) ) { xs_warn( "bad xpath\n" ); if ( xpath ) xmlFree(xpath); croak( "empty XPath found" ); XSRETURN_UNDEF; } } PPCODE: INIT_ERROR_HANDLER; if (comp) { found = domXPathCompFind( node, comp, to_bool ); } else { found = domXPathFind( node, xpath, to_bool ); xmlFree( xpath ); } CLEANUP_ERROR_HANDLER; if (found) { REPORT_ERROR(1); switch (found->type) { case XPATH_NODESET: /* return as a NodeList */ /* access ->nodesetval */ XPUSHs(sv_2mortal(newSVpv("XML::LibXML::NodeList", 0))); nodelist = found->nodesetval; if ( nodelist ) { if ( nodelist->nodeNr > 0 ) { int i; const char * cls = "XML::LibXML::Node"; xmlNodePtr tnode; SV * element; int l = nodelist->nodeNr; owner = PmmOWNERPO(SvPROXYNODE(pnode)); for( i=0 ; i < l; i++){ /* we have to create a new instance of an * objectptr. and then * place the current node into the new * object. afterwards we can * push the object to the array! */ tnode = nodelist->nodeTab[i]; /* let's be paranoid */ if (tnode->type == XML_NAMESPACE_DECL) { xmlNsPtr newns = xmlCopyNamespace((xmlNsPtr)tnode); if ( newns != NULL ) { element = NEWSV(0,0); cls = PmmNodeTypeName( tnode ); element = sv_setref_pv( element, (const char *)cls, (void*)newns ); } else { continue; } } else { element = PmmNodeToSv(tnode, owner); } XPUSHs( sv_2mortal(element) ); } } xmlXPathFreeNodeSet( found->nodesetval ); found->nodesetval = NULL; } break; case XPATH_BOOLEAN: /* return as a Boolean */ /* access ->boolval */ XPUSHs(sv_2mortal(newSVpv("XML::LibXML::Boolean", 0))); XPUSHs(sv_2mortal(newSViv(found->boolval))); break; case XPATH_NUMBER: /* return as a Number */ /* access ->floatval */ XPUSHs(sv_2mortal(newSVpv("XML::LibXML::Number", 0))); XPUSHs(sv_2mortal(newSVnv(found->floatval))); break; case XPATH_STRING: /* access ->stringval */ /* return as a Literal */ XPUSHs(sv_2mortal(newSVpv("XML::LibXML::Literal", 0))); XPUSHs(sv_2mortal(C2Sv(found->stringval, NULL))); break; default: croak("Unknown XPath return type"); } xmlXPathFreeObject(found); } else { REPORT_ERROR(0); } void _findnodes( pnode, perl_xpath ) SV* pnode SV * perl_xpath PREINIT: xmlNodePtr node = PmmSvNode(pnode); ProxyNodePtr owner = NULL; xmlNodeSetPtr nodelist = NULL; SV * element = NULL ; xmlChar * xpath = NULL ; xmlXPathCompExprPtr comp = NULL; PREINIT_SAVED_ERROR INIT: if ( node == NULL ) { if ( xpath ) xmlFree(xpath); croak( "lost node" ); } if (sv_isobject(perl_xpath) && sv_isa(perl_xpath,"XML::LibXML::XPathExpression")) { comp = INT2PTR(xmlXPathCompExprPtr,SvIV((SV*)SvRV( perl_xpath ))); if (!comp) XSRETURN_UNDEF; } else { xpath = nodeSv2C(perl_xpath, node); if ( !(xpath && xmlStrlen(xpath)) ) { xs_warn( "bad xpath\n" ); if ( xpath ) xmlFree(xpath); croak( "empty XPath found" ); XSRETURN_UNDEF; } } PPCODE: INIT_ERROR_HANDLER; if (comp) { nodelist = domXPathCompSelect( node, comp ); } else { nodelist = domXPathSelect( node, xpath ); xmlFree(xpath); } CLEANUP_ERROR_HANDLER; if ( nodelist ) { REPORT_ERROR(1); if ( nodelist->nodeNr > 0 ) { int i; int len = nodelist->nodeNr; const char * cls = "XML::LibXML::Node"; xmlNodePtr tnode; owner = PmmOWNERPO(SvPROXYNODE(pnode)); for(i=0 ; i < len; i++){ /* we have to create a new instance of an objectptr. * and then place the current node into the new object. * afterwards we can push the object to the array! */ element = NULL; tnode = nodelist->nodeTab[i]; if (tnode->type == XML_NAMESPACE_DECL) { xmlNsPtr newns = xmlCopyNamespace((xmlNsPtr)tnode); if ( newns != NULL ) { element = NEWSV(0,0); cls = PmmNodeTypeName( tnode ); element = sv_setref_pv( element, (const char *)cls, newns ); } else { continue; } } else { element = PmmNodeToSv(tnode, owner); } XPUSHs( sv_2mortal(element) ); } } xmlXPathFreeNodeSet( nodelist ); } else { REPORT_ERROR(0); } void getNamespaces( pnode ) SV * pnode ALIAS: namespaces = 1 PREINIT: xmlNodePtr node; xmlNsPtr ns = NULL; xmlNsPtr newns = NULL; SV* element = &PL_sv_undef; const char * class = "XML::LibXML::Namespace"; INIT: PERL_UNUSED_VAR(ix); node = PmmSvNode(pnode); if ( node == NULL ) { croak( "lost node" ); } PPCODE: if (node->type == XML_ELEMENT_NODE) { ns = node->nsDef; while ( ns != NULL ) { if (ns->prefix != NULL || ns->href != NULL) { newns = xmlCopyNamespace(ns); if ( newns != NULL ) { element = NEWSV(0,0); element = sv_setref_pv( element, (const char *)class, (void*)newns ); XPUSHs( sv_2mortal(element) ); } } ns = ns->next; } } SV * getNamespace( node ) xmlNodePtr node ALIAS: localNamespace = 1 localNS = 2 PREINIT: xmlNsPtr ns = NULL; xmlNsPtr newns = NULL; const char * class = "XML::LibXML::Namespace"; CODE: PERL_UNUSED_VAR(ix); if ( node->type == XML_ELEMENT_NODE || node->type == XML_ATTRIBUTE_NODE || node->type == XML_PI_NODE ) { ns = node->ns; if ( ns != NULL ) { newns = xmlCopyNamespace(ns); if ( newns != NULL ) { RETVAL = NEWSV(0,0); RETVAL = sv_setref_pv( RETVAL, (const char *)class, (void*)newns ); } else { XSRETURN_UNDEF; } } else { XSRETURN_UNDEF; } } else { XSRETURN_UNDEF; } OUTPUT: RETVAL SV * nodePath( self ) xmlNodePtr self PREINIT: xmlChar * path = NULL; CODE: path = xmlGetNodePath( self ); if ( path == NULL ) { croak( "cannot calculate path for the given node" ); } RETVAL = C2Sv( path, NULL ); xmlFree(path); OUTPUT: RETVAL int line_number( self ) xmlNodePtr self CODE: RETVAL = xmlGetLineNo( self ); OUTPUT: RETVAL MODULE = XML::LibXML PACKAGE = XML::LibXML::Element SV* new(CLASS, name ) char * name PREINIT: xmlNodePtr newNode; ProxyNodePtr docfrag = NULL; CODE: docfrag = PmmNewFragment(NULL); newNode = xmlNewNode( NULL, (const xmlChar*)name ); newNode->doc = NULL; xmlAddChild(PmmNODE(docfrag), newNode); RETVAL = PmmNodeToSv(newNode, docfrag ); OUTPUT: RETVAL int _setNamespace(self, namespaceURI, namespacePrefix = &PL_sv_undef, flag = 1 ) SV * self SV * namespaceURI SV * namespacePrefix int flag PREINIT: xmlNodePtr node = PmmSvNode(self); xmlChar * nsURI = nodeSv2C(namespaceURI,node); xmlChar * nsPrefix = NULL; xmlNsPtr ns = NULL; INIT: if ( node == NULL ) { croak( "lost node" ); } CODE: /* if ( !nsURI ){ XSRETURN_UNDEF; } */ nsPrefix = nodeSv2C(namespacePrefix, node); if ( xmlStrlen( nsPrefix ) == 0 ) { xmlFree(nsPrefix); nsPrefix = NULL; } if ( xmlStrlen( nsURI ) == 0 ) { xmlFree(nsURI); nsURI = NULL; } if ( nsPrefix == NULL && nsURI == NULL ) { /* special case: empty namespace */ if ( (ns = xmlSearchNs(node->doc, node, NULL)) && ( ns->href && xmlStrlen( ns->href ) != 0 ) ) { /* won't take it */ RETVAL = 0; } else if ( flag ) { /* no namespace */ xmlSetNs(node, NULL); RETVAL = 1; } else { RETVAL = 0; } } else if ( flag && (ns = xmlSearchNs(node->doc, node, nsPrefix)) ) { /* user just wants to set the namespace for the node */ /* try to reuse an existing declaration for the prefix */ if ( xmlStrEqual( ns->href, nsURI ) ) { RETVAL = 1; } else if ( (ns = xmlNewNs( node, nsURI, nsPrefix )) ) { RETVAL = 1; } else { RETVAL = 0; } } else if ( (ns = xmlNewNs( node, nsURI, nsPrefix )) ) RETVAL = 1; else RETVAL = 0; if ( flag && ns ) { xmlSetNs(node, ns); } if ( nsPrefix ) xmlFree(nsPrefix); if ( nsURI ) xmlFree(nsURI); OUTPUT: RETVAL int setNamespaceDeclURI( self, svprefix, newURI ) xmlNodePtr self SV * svprefix SV * newURI PREINIT: xmlChar * prefix = NULL; xmlChar * nsURI = NULL; xmlNsPtr ns; CODE: RETVAL = 0; prefix = nodeSv2C( svprefix , self ); nsURI = nodeSv2C( newURI , self ); /* null empty values */ if ( prefix && xmlStrlen(prefix) == 0) { xmlFree( prefix ); prefix = NULL; } if ( nsURI && xmlStrlen(nsURI) == 0) { xmlFree( nsURI ); nsURI = NULL; } ns = self->nsDef; while ( ns ) { if ((ns->prefix || ns->href ) && ( xmlStrcmp( ns->prefix, prefix ) == 0 )) { if (ns->href) xmlFree((char*)ns->href); ns->href = nsURI; if ( nsURI == NULL ) { domRemoveNsRefs( self, ns ); } else nsURI = NULL; /* do not free it */ RETVAL = 1; break; } else { ns = ns->next; } } if ( prefix ) xmlFree( prefix ); if ( nsURI ) xmlFree( nsURI ); OUTPUT: RETVAL int setNamespaceDeclPrefix( self, svprefix, newPrefix ) xmlNodePtr self SV * svprefix SV * newPrefix PREINIT: xmlChar * prefix = NULL; xmlChar * nsPrefix = NULL; xmlNsPtr ns; CODE: RETVAL = 0; prefix = nodeSv2C( svprefix , self ); nsPrefix = nodeSv2C( newPrefix , self ); /* null empty values */ if ( prefix != NULL && xmlStrlen(prefix) == 0) { xmlFree( prefix ); prefix = NULL; } if ( nsPrefix != NULL && xmlStrlen(nsPrefix) == 0) { xmlFree( nsPrefix ); nsPrefix = NULL; } if ( xmlStrcmp( prefix, nsPrefix ) == 0 ) { RETVAL = 1; } else { /* check that new prefix is not in scope */ ns = xmlSearchNs( self->doc, self, nsPrefix ); if ( ns != NULL ) { if (nsPrefix != NULL) xmlFree( nsPrefix ); if (prefix != NULL) xmlFree( prefix ); croak("setNamespaceDeclPrefix: prefix '%s' is in use", ns->prefix); } /* lookup the declaration */ ns = self->nsDef; while ( ns != NULL ) { if ((ns->prefix != NULL || ns->href != NULL) && xmlStrcmp( ns->prefix, prefix ) == 0 ) { if ( ns->href == NULL && nsPrefix != NULL ) { /* xmlns:foo="" - no go */ if ( prefix != NULL) xmlFree(prefix); croak("setNamespaceDeclPrefix: cannot set non-empty prefix for empty namespace"); } if ( ns->prefix != NULL ) xmlFree( (xmlChar*)ns->prefix ); ns->prefix = nsPrefix; nsPrefix = NULL; /* do not free it */ RETVAL = 1; break; } else { ns = ns->next; } } } if ( nsPrefix != NULL ) xmlFree(nsPrefix); if ( prefix != NULL) xmlFree(prefix); OUTPUT: RETVAL SV* _getNamespaceDeclURI( self, ns_prefix ) xmlNodePtr self SV * ns_prefix PREINIT: xmlChar * prefix; xmlNsPtr ns; CODE: prefix = nodeSv2C(ns_prefix, self ); if ( prefix != NULL && xmlStrlen(prefix) == 0) { xmlFree( prefix ); prefix = NULL; } RETVAL = &PL_sv_undef; ns = self->nsDef; while ( ns != NULL ) { if ( (ns->prefix != NULL || ns->href != NULL) && xmlStrcmp( ns->prefix, prefix ) == 0 ) { RETVAL = C2Sv(ns->href, NULL); break; } else { ns = ns->next; } } if ( prefix != NULL ) { xmlFree( prefix ); } OUTPUT: RETVAL int hasAttribute( self, attr_name ) xmlNodePtr self SV * attr_name PREINIT: xmlChar * name; CODE: name = nodeSv2C(attr_name, self ); if ( ! name ) { XSRETURN_UNDEF; } if ( domGetAttrNode( self, name ) ) { RETVAL = 1; } else { RETVAL = 0; } xmlFree(name); OUTPUT: RETVAL int hasAttributeNS( self, namespaceURI, attr_name ) xmlNodePtr self SV * namespaceURI SV * attr_name PREINIT: xmlChar * name; xmlChar * nsURI; xmlNodePtr attr; CODE: name = nodeSv2C(attr_name, self ); nsURI = nodeSv2C(namespaceURI, self ); if ( name == NULL ) { if ( nsURI != NULL ) { xmlFree(nsURI); } XSRETURN_UNDEF; } if ( nsURI != NULL && xmlStrlen(nsURI) == 0 ){ xmlFree(nsURI); nsURI = NULL; } attr = (xmlNodePtr) xmlHasNsProp( self, name, nsURI ); if ( attr && attr->type == XML_ATTRIBUTE_NODE ) { RETVAL = 1; } else { RETVAL = 0; } xmlFree(name); if ( nsURI != NULL ){ xmlFree(nsURI); } OUTPUT: RETVAL SV* _getAttribute( self, attr_name, useDomEncoding = 0 ) xmlNodePtr self SV * attr_name int useDomEncoding PREINIT: xmlChar * name; xmlChar * prefix = NULL; xmlChar * localname = NULL; xmlChar * ret = NULL; xmlNsPtr ns = NULL; CODE: name = nodeSv2C(attr_name, self ); if( !name ) { XSRETURN_UNDEF; } ret = xmlGetNoNsProp(self, name); if ( ret == NULL ) { localname = xmlSplitQName2(name, &prefix); if ( localname != NULL ) { ns = xmlSearchNs( self->doc, self, prefix ); if ( ns != NULL ) { ret = xmlGetNsProp(self, localname, ns->href); } if ( prefix != NULL) { xmlFree( prefix ); } xmlFree( localname ); } } xmlFree(name); if ( ret ) { if ( useDomEncoding ) { RETVAL = nodeC2Sv(ret, self); } else { RETVAL = C2Sv(ret, NULL); } xmlFree( ret ); } else { XSRETURN_UNDEF; } OUTPUT: RETVAL void _setAttribute( self, attr_name, attr_value ) xmlNodePtr self SV * attr_name SV * attr_value PREINIT: xmlChar * name = NULL; xmlChar * value = NULL; #if LIBXML_VERSION < 20621 xmlChar * prefix = NULL; xmlChar * localname = NULL; #endif CODE: name = nodeSv2C(attr_name, self ); if ( !LibXML_test_node_name(name) ) { xmlFree(name); croak( "bad name" ); } value = nodeSv2C(attr_value, self ); #if LIBXML_VERSION >= 20621 /* * For libxml2-2.6.21 and later we can use just xmlSetProp */ xmlSetProp(self,name,value); #else /* * but xmlSetProp does not work correctly for older libxml2 versions * The following is copied from libxml2 source * with xmlSplitQName3 replaced by xmlSplitQName2 for compatibility * with older libxml2 versions */ localname = xmlSplitQName2(name, &prefix); if (localname != NULL) { xmlNsPtr ns; ns = xmlSearchNs(self->doc, self, prefix); if (prefix != NULL) xmlFree(prefix); if (ns != NULL) xmlSetNsProp(self, ns, localname, value); else xmlSetNsProp(self, NULL, name, value); xmlFree(localname); } else { xmlSetNsProp(self, NULL, name, value); } #endif xmlFree(name); xmlFree(value); void removeAttribute( self, attr_name ) xmlNodePtr self SV * attr_name PREINIT: xmlChar * name; xmlAttrPtr xattr = NULL; CODE: name = nodeSv2C(attr_name, self ); if ( name ) { xattr = domGetAttrNode( self, name ); if ( xattr ) { xmlUnlinkNode((xmlNodePtr)xattr); if ( xattr->_private ) { PmmFixOwner((ProxyNodePtr)xattr->_private, NULL); } else { xmlFreeProp(xattr); } } xmlFree(name); } SV* getAttributeNode( self, attr_name ) xmlNodePtr self SV * attr_name PREINIT: xmlChar * name; xmlAttrPtr ret = NULL; CODE: name = nodeSv2C(attr_name, self ); if ( !name ) { XSRETURN_UNDEF; } ret = domGetAttrNode( self, name ); xmlFree(name); if ( ret ) { RETVAL = PmmNodeToSv( (xmlNodePtr)ret, PmmOWNERPO(PmmPROXYNODE(self)) ); } else { XSRETURN_UNDEF; } OUTPUT: RETVAL SV * setAttributeNode( self, attr_node ) xmlNodePtr self SV * attr_node PREINIT: xmlAttrPtr attr = (xmlAttrPtr)PmmSvNode( attr_node ); xmlAttrPtr ret = NULL; INIT: if ( attr == NULL ) { croak( "lost attribute" ); } CODE: if ( attr != NULL && attr->type != XML_ATTRIBUTE_NODE ) { XSRETURN_UNDEF; } if ( attr->doc != self->doc ) { domImportNode( self->doc, (xmlNodePtr)attr, 1, 1); } ret = domGetAttrNode( self, attr->name ); if ( ret != NULL ) { if ( ret != attr ) { xmlReplaceNode( (xmlNodePtr)ret, (xmlNodePtr)attr ); } else { XSRETURN_UNDEF; } } else { xmlAddChild( self, (xmlNodePtr)attr ); } if ( attr->_private != NULL ) { PmmFixOwner( SvPROXYNODE(attr_node), PmmPROXYNODE(self) ); } if ( ret == NULL ) { XSRETURN_UNDEF; } RETVAL = PmmNodeToSv( (xmlNodePtr)ret, NULL ); PmmFixOwner( SvPROXYNODE(RETVAL), NULL ); OUTPUT: RETVAL SV * _getAttributeNS( self, namespaceURI, attr_name, useDomEncoding = 0 ) xmlNodePtr self SV * namespaceURI SV * attr_name int useDomEncoding PREINIT: xmlChar * name; xmlChar * nsURI; xmlChar * ret = NULL; CODE: name = nodeSv2C( attr_name, self ); nsURI = nodeSv2C( namespaceURI, self ); if ( !name ) { xmlFree(nsURI); XSRETURN_UNDEF; } if ( nsURI && xmlStrlen(nsURI) ) { ret = xmlGetNsProp( self, name, nsURI ); } else { ret = xmlGetProp( self, name ); } xmlFree( name ); if ( nsURI ) { xmlFree( nsURI ); } if ( ret ) { if (useDomEncoding) { RETVAL = nodeC2Sv( ret, self ); } else { RETVAL = C2Sv( ret, NULL ); } xmlFree( ret ); } else { XSRETURN_UNDEF; } OUTPUT: RETVAL void _setAttributeNS( self, namespaceURI, attr_name, attr_value ) xmlNodePtr self SV * namespaceURI SV * attr_name SV * attr_value PREINIT: xmlChar * nsURI; xmlChar * name = NULL; xmlChar * value = NULL; xmlNsPtr ns = NULL; xmlChar * localname = NULL; xmlChar * prefix = NULL; xmlNsPtr * all_ns = NULL; int i; INIT: name = nodeSv2C( attr_name, self ); if ( !LibXML_test_node_name(name) ) { xmlFree(name); croak( "bad name" ); } nsURI = nodeSv2C( namespaceURI, self ); localname = xmlSplitQName2(name, &prefix); if ( localname ) { xmlFree( name ); name = localname; } CODE: value = nodeSv2C( attr_value, self ); if ( nsURI && xmlStrlen(nsURI) ) { xs_warn( "found uri" ); ns = xmlSearchNsByHref( self->doc, self, nsURI ); /* * check for any prefixed namespaces occluded by a default namespace * because xmlSearchNsByHref will return default namespaces unless * you are searching on an attribute node, which may not exist yet */ if ( ns && !ns->prefix ) { all_ns = xmlGetNsList(self->doc, self); if ( all_ns ) { i = 0; ns = all_ns[i]; while ( ns ) { if ( ns->prefix && xmlStrEqual(ns->href, nsURI) ) { break; } ns = all_ns[i++]; } xmlFree(all_ns); } } if ( !ns ) { /* create new ns */ if ( prefix && xmlStrlen( prefix ) ) { ns = xmlNewNs(self, nsURI , prefix); } else { ns = NULL; } } } if ( nsURI && xmlStrlen(nsURI) && !ns ) { if ( prefix ) xmlFree( prefix ); if ( nsURI ) xmlFree( nsURI ); xmlFree( name ); xmlFree( value ); croak( "bad ns attribute!" ); } else { /* warn( "set attribute %s->%s", name, value ); */ xmlSetNsProp( self, ns, name, value ); } if ( prefix ) { xmlFree( prefix ); } if ( nsURI ) { xmlFree( nsURI ); } xmlFree( name ); xmlFree( value ); void removeAttributeNS( self, namespaceURI, attr_name ) xmlNodePtr self SV * namespaceURI SV * attr_name PREINIT: xmlChar * nsURI; xmlChar * name = NULL; xmlAttrPtr xattr = NULL; CODE: nsURI = nodeSv2C( namespaceURI, self ); name = nodeSv2C( attr_name, self ); if ( ! name ) { xmlFree(nsURI); XSRETURN_UNDEF; } if ( nsURI && xmlStrlen(nsURI) ) { xattr = xmlHasNsProp( self, name, nsURI ); } else { xattr = xmlHasNsProp( self, name, NULL ); } if ( xattr && xattr->type == XML_ATTRIBUTE_NODE ) { xmlUnlinkNode((xmlNodePtr)xattr); if ( xattr->_private ) { PmmFixOwner((ProxyNodePtr)xattr->_private, NULL); } else { xmlFreeProp(xattr); } } xmlFree(nsURI); xmlFree( name ); SV* getAttributeNodeNS( self,namespaceURI, attr_name ) xmlNodePtr self SV * namespaceURI SV * attr_name PREINIT: xmlChar * nsURI; xmlChar * name; xmlAttrPtr ret = NULL; CODE: nsURI = nodeSv2C(namespaceURI, self ); name = nodeSv2C(attr_name, self ); if ( !name ) { xmlFree(nsURI); XSRETURN_UNDEF; } if ( nsURI && xmlStrlen(nsURI) ) { ret = xmlHasNsProp( self, name, nsURI ); } else { ret = xmlHasNsProp( self, name, NULL ); } xmlFree(name); if ( nsURI ) { xmlFree(nsURI); } if ( ret && ret->type == XML_ATTRIBUTE_NODE /* we don't want fixed attribute decls */ ) { RETVAL = PmmNodeToSv( (xmlNodePtr)ret, PmmOWNERPO(PmmPROXYNODE(self)) ); } else { /* warn("no prop\n"); */ XSRETURN_UNDEF; } OUTPUT: RETVAL SV * setAttributeNodeNS( self, attr_node ) xmlNodePtr self SV * attr_node PREINIT: xmlAttrPtr attr = (xmlAttrPtr)PmmSvNode( attr_node ); xmlNsPtr ns = NULL; xmlAttrPtr ret = NULL; INIT: if ( attr == NULL ) { croak( "lost attribute node" ); } CODE: if ( attr->type != XML_ATTRIBUTE_NODE ) { XSRETURN_UNDEF; } if ( attr->doc != self->doc ) { domImportNode( self->doc, (xmlNodePtr)attr, 1,1); } ns = attr->ns; if ( ns != NULL ) { ret = xmlHasNsProp( self, ns->href, attr->name ); } else { ret = xmlHasNsProp( self, NULL, attr->name ); } if ( ret && ret->type == XML_ATTRIBUTE_NODE ) { if ( ret != attr ) { xmlReplaceNode( (xmlNodePtr)ret, (xmlNodePtr)attr ); } else { XSRETURN_UNDEF; } } else { xmlAddChild( self, (xmlNodePtr)attr ); xmlReconciliateNs(self->doc, self); } if ( attr->_private != NULL ) { PmmFixOwner( SvPROXYNODE(attr_node), PmmPROXYNODE(self) ); } if ( ret != NULL && ret->type == XML_ATTRIBUTE_NODE ) { RETVAL = PmmNodeToSv( (xmlNodePtr)ret, NULL ); PmmFixOwner( SvPROXYNODE(RETVAL), NULL ); } else { XSRETURN_UNDEF; } OUTPUT: RETVAL SV * removeAttributeNode( self, attr_node ) xmlNodePtr self SV * attr_node PREINIT: xmlAttrPtr attr = (xmlAttrPtr)PmmSvNode( attr_node ); xmlAttrPtr ret; INIT: if ( attr == NULL ) { croak( "lost attribute node" ); } CODE: if ( attr->type != XML_ATTRIBUTE_NODE ) { XSRETURN_UNDEF; } if ( attr->parent != self ) { XSRETURN_UNDEF; } ret = attr; xmlUnlinkNode( (xmlNodePtr)attr ); RETVAL = PmmNodeToSv( (xmlNodePtr)ret, NULL ); PmmFixOwner( SvPROXYNODE(RETVAL), NULL ); OUTPUT: RETVAL void appendText( self, string ) xmlNodePtr self SV * string ALIAS: appendTextNode = 1 XML::LibXML::DocumentFragment::appendText = 2 XML::LibXML::DocumentFragment::appendTextNode = 3 PREINIT: xmlChar * content = NULL; INIT: PERL_UNUSED_VAR(ix); content = nodeSv2C( string, self ); if ( content == NULL ) { XSRETURN_UNDEF; } if ( xmlStrlen(content) == 0 ) { xmlFree( content ); XSRETURN_UNDEF; } CODE: xmlNodeAddContent( self, content ); xmlFree(content); void appendTextChild( self, strname, strcontent=&PL_sv_undef, nsURI=&PL_sv_undef ) xmlNodePtr self SV * strname SV * strcontent SV * nsURI PREINIT: xmlChar * name; xmlChar * content = NULL; xmlChar * encstr = NULL; INIT: name = nodeSv2C( strname, self ); if ( xmlStrlen(name) == 0 ) { xmlFree(name); XSRETURN_UNDEF; } CODE: content = nodeSv2C(strcontent, self); if ( content && xmlStrlen( content ) == 0 ) { xmlFree(content); content=NULL; } else if ( content ) { encstr = xmlEncodeEntitiesReentrant( self->doc, content ); xmlFree(content); } xmlNewChild( self, NULL, name, encstr ); if ( encstr ) xmlFree(encstr); xmlFree(name); SV * addNewChild( self, namespaceURI, nodename ) xmlNodePtr self SV * namespaceURI SV * nodename ALIAS: XML::LibXML::DocumentFragment::addNewChild = 1 PREINIT: xmlChar * nsURI = NULL; xmlChar * name = NULL; xmlChar * localname = NULL; xmlChar * prefix = NULL; xmlNodePtr newNode = NULL; xmlNodePtr prev = NULL; xmlNsPtr ns = NULL; CODE: PERL_UNUSED_VAR(ix); name = nodeSv2C(nodename, self); if ( name && xmlStrlen( name ) == 0 ) { xmlFree(name); XSRETURN_UNDEF; } nsURI = nodeSv2C(namespaceURI, self); if ( nsURI && xmlStrlen( nsURI ) == 0 ) { xmlFree(nsURI); nsURI=NULL; } if ( nsURI != NULL ) { localname = xmlSplitQName2(name, &prefix); ns = xmlSearchNsByHref(self->doc, self, nsURI); newNode = xmlNewDocNode(self->doc, ns, localname?localname:name, NULL); if ( ns == NULL ) { xmlSetNs(newNode,xmlNewNs(newNode, nsURI, prefix)); } xmlFree(localname); xmlFree(prefix); xmlFree(nsURI); } else { newNode = xmlNewDocNode(self->doc, NULL, name, NULL); } xmlFree(name); /* add the node to the parent node */ newNode->type = XML_ELEMENT_NODE; newNode->parent = self; newNode->doc = self->doc; if (self->children == NULL) { self->children = newNode; self->last = newNode; } else { prev = self->last; prev->next = newNode; newNode->prev = prev; self->last = newNode; } RETVAL = PmmNodeToSv(newNode, PmmOWNERPO(PmmPROXYNODE(self)) ); OUTPUT: RETVAL MODULE = XML::LibXML PACKAGE = XML::LibXML::Text SV * new( CLASS, content ) SV * content PREINIT: xmlChar * data; xmlNodePtr newNode; ProxyNodePtr docfrag = NULL; CODE: data = Sv2C(content, NULL); newNode = xmlNewText( data ); xmlFree(data); if( newNode != NULL ) { docfrag = PmmNewFragment( NULL ); xmlAddChild(PmmNODE(docfrag), newNode); RETVAL = PmmNodeToSv(newNode,docfrag); } else { XSRETURN_UNDEF; } OUTPUT: RETVAL SV * substringData( self, offset, length ) xmlNodePtr self int offset int length PREINIT: xmlChar * data = NULL; xmlChar * substr = NULL; CODE: if ( offset >= 0 && length >= 0 ) { data = domGetNodeValue( self ); if ( data != NULL ) { substr = xmlUTF8Strsub( data, offset, length ); RETVAL = C2Sv( (const xmlChar*)substr, NULL ); xmlFree( substr ); } else { XSRETURN_UNDEF; } } else { XSRETURN_UNDEF; } OUTPUT: RETVAL void setData( self, value ) xmlNodePtr self SV * value ALIAS: XML::LibXML::Attr::setValue = 1 XML::LibXML::PI::_setData = 2 PREINIT: xmlChar * encstr = NULL; CODE: PERL_UNUSED_VAR(ix); encstr = nodeSv2C(value,self); domSetNodeValue( self, encstr ); xmlFree(encstr); void appendData( self, value ) xmlNodePtr self SV * value PREINIT: xmlChar * encstring = NULL; int strlen = 0; CODE: encstring = Sv2C( value, self->doc!=NULL ? self->doc->encoding : NULL ); if ( encstring != NULL ) { strlen = xmlStrlen( encstring ); xmlTextConcat( self, encstring, strlen ); xmlFree( encstring ); } void insertData( self, offset, value ) xmlNodePtr self int offset SV * value PREINIT: xmlChar * after= NULL; xmlChar * data = NULL; xmlChar * new = NULL; xmlChar * encstring = NULL; int dl = 0; CODE: if ( offset >= 0 ) { encstring = Sv2C( value, self->doc!=NULL ? self->doc->encoding : NULL ); if ( encstring != NULL && xmlStrlen( encstring ) > 0 ) { data = domGetNodeValue(self); if ( data != NULL && xmlStrlen( data ) > 0 ) { if ( xmlUTF8Strlen( data ) < offset ) { data = xmlStrcat( data, encstring ); domSetNodeValue( self, data ); } else { dl = xmlUTF8Strlen( data ) - offset; if ( offset > 0 ) new = xmlUTF8Strsub(data, 0, offset ); after = xmlUTF8Strsub(data, offset, dl ); if ( new != NULL ) { new = xmlStrcat(new, encstring ); } else { new = xmlStrdup( encstring ); } if ( after != NULL ) new = xmlStrcat(new, after ); domSetNodeValue( self, new ); xmlFree( new ); xmlFree( after ); } xmlFree( data ); } else { domSetNodeValue( self, encstring ); } xmlFree(encstring); } } void deleteData( self, offset, length ) xmlNodePtr self int offset int length PREINIT: xmlChar * data = NULL; xmlChar * after = NULL; xmlChar * new = NULL; int len = 0; int dl1 = 0; int dl2 = 0; CODE: if ( length > 0 && offset >= 0 ) { data = domGetNodeValue(self); len = xmlUTF8Strlen( data ); if ( data != NULL && len > 0 && len > offset ) { dl1 = offset + length; if ( offset > 0 ) new = xmlUTF8Strsub( data, 0, offset ); if ( len > dl1 ) { dl2 = len - dl1; after = xmlUTF8Strsub( data, dl1, dl2 ); if ( new != NULL ) { new = xmlStrcat( new, after ); xmlFree(after); } else { new = after; } } domSetNodeValue( self, new ); xmlFree(new); } } void replaceData( self, offset,length, value ) xmlNodePtr self int offset int length SV * value PREINIT: xmlChar * after= NULL; xmlChar * data = NULL; xmlChar * new = NULL; xmlChar * encstring = NULL; int len = 0; int dl1 = 0; int dl2 = 0; CODE: if ( offset >= 0 ) { encstring = Sv2C( value, self->doc!=NULL ? self->doc->encoding : NULL ); if ( encstring != NULL && xmlStrlen( encstring ) > 0 ) { data = domGetNodeValue(self); len = xmlUTF8Strlen( data ); if ( data != NULL && len > 0 && len > offset ) { dl1 = offset + length; if ( dl1 < len ) { dl2 = xmlUTF8Strlen( data ) - dl1; if ( offset > 0 ) { new = xmlUTF8Strsub(data, 0, offset ); new = xmlStrcat(new, encstring ); } else { new = xmlStrdup( encstring ); } after = xmlUTF8Strsub(data, dl1, dl2 ); new = xmlStrcat(new, after ); domSetNodeValue( self, new ); xmlFree( new ); xmlFree( after ); } else { /* replace until end! */ if ( offset > 0 ) { new = xmlUTF8Strsub(data, 0, offset ); new = xmlStrcat(new, encstring ); } else { new = xmlStrdup( encstring ); } domSetNodeValue( self, new ); xmlFree( new ); } xmlFree( data ); } xmlFree(encstring); } } MODULE = XML::LibXML PACKAGE = XML::LibXML::Comment SV * new( CLASS, content ) SV * content PREINIT: xmlChar * encstring; xmlNodePtr newNode; ProxyNodePtr docfrag = NULL; CODE: encstring = Sv2C(content, NULL); newNode = xmlNewComment( encstring ); xmlFree(encstring); if( newNode != NULL ) { docfrag = PmmNewFragment( NULL ); xmlAddChild(PmmNODE(docfrag), newNode); RETVAL = PmmNodeToSv(newNode,docfrag); } else { XSRETURN_UNDEF; } OUTPUT: RETVAL MODULE = XML::LibXML PACKAGE = XML::LibXML::CDATASection SV * new( CLASS , content ) SV * content PREINIT: xmlChar * encstring; xmlNodePtr newNode; ProxyNodePtr docfrag = NULL; CODE: encstring = Sv2C(content, NULL); newNode = xmlNewCDataBlock( NULL , encstring, xmlStrlen( encstring ) ); xmlFree(encstring); if ( newNode != NULL ){ docfrag = PmmNewFragment( NULL ); xmlAddChild(PmmNODE(docfrag), newNode); RETVAL = PmmNodeToSv(newNode,docfrag); } else { XSRETURN_UNDEF; } OUTPUT: RETVAL MODULE = XML::LibXML PACKAGE = XML::LibXML::DocumentFragment SV* new( CLASS ) PREINIT: xmlNodePtr real_doc=NULL; CODE: real_doc = xmlNewDocFragment( NULL ); RETVAL = PmmNodeToSv( real_doc, NULL ); OUTPUT: RETVAL MODULE = XML::LibXML PACKAGE = XML::LibXML::Attr SV* new( CLASS, pname, pvalue ) SV * pname SV * pvalue PREINIT: xmlNodePtr attr = NULL; xmlChar * name; xmlChar * value; CODE: name = Sv2C(pname,NULL); value = Sv2C(pvalue,NULL); if ( name == NULL ) { XSRETURN_UNDEF; } attr = (xmlNodePtr)xmlNewProp( NULL, name, value ); attr->doc = NULL; RETVAL = PmmNodeToSv(attr,NULL); OUTPUT: RETVAL SV* parentElement( self ) ALIAS: XML::LibXML::Attr::getParentNode = 1 XML::LibXML::Attr::getNextSibling = 2 XML::LibXML::Attr::getPreviousSibling = 3 XML::LibXML::Attr::nextSibling = 4 XML::LibXML::Attr::previousSibling = 5 CODE: /* override the original parentElement(), since this an attribute is * not part of the main tree */ PERL_UNUSED_VAR(ix); XSRETURN_UNDEF; OUTPUT: RETVAL SV* serializeContent( self, useDomEncoding = &PL_sv_undef ) SV * self SV * useDomEncoding PREINIT: xmlBufferPtr buffer; const xmlChar *ret = NULL; xmlAttrPtr node = (xmlAttrPtr)PmmSvNode(self); CODE: buffer = xmlBufferCreate(); domAttrSerializeContent(buffer, node); if ( xmlBufferLength(buffer) > 0 ) { ret = xmlBufferContent( buffer ); } if ( ret != NULL ) { if ( useDomEncoding != &PL_sv_undef && SvTRUE(useDomEncoding) ) { RETVAL = nodeC2Sv((xmlChar*)ret, PmmNODE(PmmPROXYNODE(node))) ; } else { RETVAL = C2Sv((xmlChar*)ret, NULL) ; } xmlBufferFree( buffer ); } else { xmlBufferFree( buffer ); xs_warn("Failed to convert attribute to string"); XSRETURN_UNDEF; } OUTPUT: RETVAL SV* toString(self , format=0, useDomEncoding = &PL_sv_undef ) SV * self SV * useDomEncoding int format ALIAS: XML::LibXML::Attr::serialize = 1 PREINIT: xmlAttrPtr node = (xmlAttrPtr)PmmSvNode(self); xmlBufferPtr buffer; const xmlChar *ret = NULL; CODE: /* we add an extra method for serializing attributes since XML::LibXML::Node::toString causes segmentation fault inside libxml2 */ PERL_UNUSED_VAR(ix); buffer = xmlBufferCreate(); xmlBufferAdd(buffer, BAD_CAST " ", 1); if ((node->ns != NULL) && (node->ns->prefix != NULL)) { xmlBufferAdd(buffer, node->ns->prefix, xmlStrlen(node->ns->prefix)); xmlBufferAdd(buffer, BAD_CAST ":", 1); } xmlBufferAdd(buffer, node->name, xmlStrlen(node->name)); xmlBufferAdd(buffer, BAD_CAST "=\"", 2); domAttrSerializeContent(buffer, node); xmlBufferAdd(buffer, BAD_CAST "\"", 1); if ( xmlBufferLength(buffer) > 0 ) { ret = xmlBufferContent( buffer ); } if ( ret != NULL ) { if ( useDomEncoding != &PL_sv_undef && SvTRUE(useDomEncoding) ) { RETVAL = nodeC2Sv((xmlChar*)ret, PmmNODE(PmmPROXYNODE(node))) ; } else { RETVAL = C2Sv((xmlChar*)ret, NULL) ; } xmlBufferFree( buffer ); } else { xmlBufferFree( buffer ); xs_warn("Failed to convert attribute to string"); XSRETURN_UNDEF; } OUTPUT: RETVAL int _setNamespace(self, namespaceURI, namespacePrefix = &PL_sv_undef ) SV * self SV * namespaceURI SV * namespacePrefix PREINIT: xmlAttrPtr node = (xmlAttrPtr)PmmSvNode(self); xmlChar * nsURI = nodeSv2C(namespaceURI,(xmlNodePtr)node); xmlChar * nsPrefix = NULL; xmlNsPtr ns = NULL; INIT: if ( node == NULL ) { croak( "lost node" ); } CODE: if ( !nsURI || xmlStrlen(nsURI)==0 ){ xmlSetNs((xmlNodePtr)node, NULL); RETVAL = 1; } if ( !node->parent ) { XSRETURN_UNDEF; } nsPrefix = nodeSv2C(namespacePrefix, (xmlNodePtr)node); if ( (ns = xmlSearchNs(node->doc, node->parent, nsPrefix)) && xmlStrEqual( ns->href, nsURI) ) { /* same uri and prefix */ RETVAL = 1; } else if ( (ns = xmlSearchNsByHref(node->doc, node->parent, nsURI)) ) { /* set uri, but with a different prefix */ RETVAL = 1; } else if (! RETVAL) RETVAL = 0; if ( ns ) { if ( ns->prefix ) { xmlSetNs((xmlNodePtr)node, ns); } else { RETVAL = 0; } } xmlFree(nsPrefix); xmlFree(nsURI); OUTPUT: RETVAL int isId( self ) SV * self PREINIT: xmlAttrPtr attr = (xmlAttrPtr)PmmSvNode(self); xmlNodePtr elem; CODE: if ( attr == NULL ) { XSRETURN_UNDEF; } elem = attr->parent; if ( elem == NULL || elem->doc == NULL ) { XSRETURN_UNDEF; } RETVAL = xmlIsID( elem->doc, elem, attr ); OUTPUT: RETVAL MODULE = XML::LibXML PACKAGE = XML::LibXML::Namespace SV* new(CLASS, namespaceURI, namespacePrefix=&PL_sv_undef) const char * CLASS SV * namespaceURI SV * namespacePrefix PREINIT: xmlNsPtr ns = NULL; xmlChar* nsURI; xmlChar* nsPrefix; CODE: RETVAL = &PL_sv_undef; nsURI = Sv2C(namespaceURI,NULL); if ( !nsURI ) { XSRETURN_UNDEF; } nsPrefix = Sv2C(namespacePrefix, NULL); ns = xmlNewNs(NULL, nsURI, nsPrefix); if ( ns ) { RETVAL = NEWSV(0,0); RETVAL = sv_setref_pv( RETVAL, CLASS, (void*)ns); } xmlFree(nsURI); if ( nsPrefix ) xmlFree(nsPrefix); OUTPUT: RETVAL void DESTROY(self) SV * self PREINIT: xmlNsPtr ns = INT2PTR(xmlNsPtr,SvIV(SvRV(self))); CODE: xs_warn( "DESTROY NS" ); if (ns) { xmlFreeNs(ns); } int nodeType(self) SV * self ALIAS: getType = 1 PREINIT: xmlNsPtr ns = INT2PTR(xmlNsPtr,SvIV(SvRV(self))); CODE: PERL_UNUSED_VAR(ix); RETVAL = ns->type; OUTPUT: RETVAL SV* declaredURI(self) SV * self ALIAS: value = 1 nodeValue = 2 getData = 3 getValue = 4 value2 = 5 href = 6 PREINIT: xmlNsPtr ns = INT2PTR(xmlNsPtr,SvIV(SvRV(self))); xmlChar * href; CODE: PERL_UNUSED_VAR(ix); href = xmlStrdup(ns->href); RETVAL = C2Sv(href, NULL); xmlFree(href); OUTPUT: RETVAL SV* declaredPrefix(self) SV * self ALIAS: localname = 1 getLocalName = 2 PREINIT: xmlNsPtr ns = INT2PTR(xmlNsPtr,SvIV(SvRV(self))); xmlChar * prefix; CODE: PERL_UNUSED_VAR(ix); prefix = xmlStrdup(ns->prefix); RETVAL = C2Sv(prefix, NULL); xmlFree(prefix); OUTPUT: RETVAL SV* unique_key( self ) SV * self PREINIT: xmlNsPtr ns = INT2PTR(xmlNsPtr,SvIV(SvRV(self))); xmlChar* key; CODE: /* Concatenate prefix and URI with vertical bar dividing*/ key = xmlStrdup(ns->prefix); key = xmlStrcat(key, (const xmlChar*)"|"); key = xmlStrcat(key, ns->href); RETVAL = C2Sv(key, NULL); OUTPUT: RETVAL int _isEqual(self, ref_node) SV * self SV * ref_node PREINIT: xmlNsPtr ns = INT2PTR(xmlNsPtr,SvIV(SvRV(self))); xmlNsPtr ons = INT2PTR(xmlNsPtr,SvIV(SvRV(ref_node))); CODE: RETVAL = 0; if ( ns == ons ) { RETVAL = 1; } else if ( xmlStrEqual(ns->href, ons->href) && xmlStrEqual(ns->prefix, ons->prefix) ) { RETVAL = 1; } OUTPUT: RETVAL MODULE = XML::LibXML PACKAGE = XML::LibXML::Dtd SV * new(CLASS, external, system) char * external char * system ALIAS: parse_uri = 1 PREINIT: xmlDtdPtr dtd = NULL; PREINIT_SAVED_ERROR CODE: PERL_UNUSED_VAR(ix); INIT_ERROR_HANDLER; dtd = xmlParseDTD((const xmlChar*)external, (const xmlChar*)system); if ( dtd == NULL ) { CLEANUP_ERROR_HANDLER; REPORT_ERROR(0); XSRETURN_UNDEF; } else { xmlSetTreeDoc((xmlNodePtr)dtd, NULL); RETVAL = PmmNodeToSv( (xmlNodePtr) dtd, NULL ); CLEANUP_ERROR_HANDLER; REPORT_ERROR(0); } OUTPUT: RETVAL SV* systemId( self ) xmlDtdPtr self ALIAS: getSystemId = 1 CODE: PERL_UNUSED_VAR(ix); if ( self->SystemID == NULL ) { XSRETURN_UNDEF; } else { RETVAL = C2Sv(self->SystemID,NULL); } OUTPUT: RETVAL SV* publicId( self ) xmlDtdPtr self ALIAS: getPublicId = 1 CODE: PERL_UNUSED_VAR(ix); if ( self->ExternalID == NULL ) { XSRETURN_UNDEF; } else { RETVAL = C2Sv(self->ExternalID,NULL); } OUTPUT: RETVAL SV * parse_string(CLASS, str, ...) char * str PREINIT: xmlDtdPtr res; SV * encoding_sv; xmlParserInputBufferPtr buffer; xmlCharEncoding enc = XML_CHAR_ENCODING_NONE; xmlChar * new_string; PREINIT_SAVED_ERROR CODE: INIT_ERROR_HANDLER; if (items > 2) { encoding_sv = ST(2); if (items > 3) { CLEANUP_ERROR_HANDLER; croak("parse_string: too many parameters"); } /* warn("getting encoding...\n"); */ enc = xmlParseCharEncoding(SvPV_nolen(encoding_sv)); if (enc == XML_CHAR_ENCODING_ERROR) { CLEANUP_ERROR_HANDLER; REPORT_ERROR(1); croak("Parse of encoding %s failed", SvPV_nolen(encoding_sv)); } } buffer = xmlAllocParserInputBuffer(enc); /* buffer = xmlParserInputBufferCreateMem(str, xmlStrlen(str), enc); */ if ( !buffer) { CLEANUP_ERROR_HANDLER; REPORT_ERROR(1); croak("cannot create buffer!\n" ); } new_string = xmlStrdup((const xmlChar*)str); xmlParserInputBufferPush(buffer, xmlStrlen(new_string), (const char*)new_string); res = xmlIOParseDTD(NULL, buffer, enc); /* NOTE: xmlIOParseDTD is documented to free its InputBuffer */ xmlFree(new_string); if ( res && LibXML_will_die_ctx(saved_error, 0) ) xmlFreeDtd( res ); CLEANUP_ERROR_HANDLER; REPORT_ERROR(0); if (res == NULL) { croak("no DTD parsed!"); } RETVAL = PmmNodeToSv((xmlNodePtr)res, NULL); OUTPUT: RETVAL #ifdef HAVE_SCHEMAS MODULE = XML::LibXML PACKAGE = XML::LibXML::RelaxNG void DESTROY( self ) xmlRelaxNGPtr self CODE: xmlRelaxNGFree( self ); xmlRelaxNGPtr parse_location( self, url ) char * url PREINIT: const char * CLASS = "XML::LibXML::RelaxNG"; xmlRelaxNGParserCtxtPtr rngctxt = NULL; PREINIT_SAVED_ERROR CODE: INIT_ERROR_HANDLER; rngctxt = xmlRelaxNGNewParserCtxt( url ); if ( rngctxt == NULL ) { croak( "failed to initialize RelaxNG parser" ); } #ifndef WITH_SERRORS /* Register Error callbacks */ xmlRelaxNGSetParserErrors( rngctxt, (xmlRelaxNGValidityErrorFunc)LibXML_error_handler_ctx, (xmlRelaxNGValidityWarningFunc)LibXML_error_handler_ctx, saved_error ); #endif RETVAL = xmlRelaxNGParse( rngctxt ); xmlRelaxNGFreeParserCtxt( rngctxt ); CLEANUP_ERROR_HANDLER; REPORT_ERROR((RETVAL == NULL) ? 0 : 1); OUTPUT: RETVAL xmlRelaxNGPtr parse_buffer( self, perlstring ) SV * perlstring PREINIT: const char * CLASS = "XML::LibXML::RelaxNG"; xmlRelaxNGParserCtxtPtr rngctxt = NULL; char * string = NULL; STRLEN len = 0; PREINIT_SAVED_ERROR INIT: string = SvPV( perlstring, len ); if ( string == NULL ) { croak( "cannot parse empty string" ); } CODE: INIT_ERROR_HANDLER; rngctxt = xmlRelaxNGNewMemParserCtxt( string,len ); if ( rngctxt == NULL ) { croak( "failed to initialize RelaxNG parser" ); } #ifndef WITH_SERRORS /* Register Error callbacks */ xmlRelaxNGSetParserErrors( rngctxt, (xmlRelaxNGValidityErrorFunc)LibXML_error_handler_ctx, (xmlRelaxNGValidityWarningFunc)LibXML_error_handler_ctx, saved_error ); #endif RETVAL = xmlRelaxNGParse( rngctxt ); xmlRelaxNGFreeParserCtxt( rngctxt ); CLEANUP_ERROR_HANDLER; REPORT_ERROR((RETVAL == NULL) ? 0 : 1); OUTPUT: RETVAL xmlRelaxNGPtr parse_document( self, doc ) xmlDocPtr doc PREINIT: const char * CLASS = "XML::LibXML::RelaxNG"; xmlRelaxNGParserCtxtPtr rngctxt = NULL; PREINIT_SAVED_ERROR CODE: INIT_ERROR_HANDLER; rngctxt = xmlRelaxNGNewDocParserCtxt( doc ); if ( rngctxt == NULL ) { croak( "failed to initialize RelaxNG parser" ); } #ifndef WITH_SERRORS /* Register Error callbacks */ xmlRelaxNGSetParserErrors( rngctxt, (xmlRelaxNGValidityErrorFunc) LibXML_error_handler_ctx, (xmlRelaxNGValidityWarningFunc)LibXML_error_handler_ctx, saved_error ); #endif RETVAL = xmlRelaxNGParse( rngctxt ); xmlRelaxNGFreeParserCtxt( rngctxt ); CLEANUP_ERROR_HANDLER; REPORT_ERROR((RETVAL == NULL) ? 0 : 1); OUTPUT: RETVAL int validate( self, doc ) xmlRelaxNGPtr self xmlDocPtr doc PREINIT: xmlRelaxNGValidCtxtPtr vctxt = NULL; PREINIT_SAVED_ERROR CODE: INIT_ERROR_HANDLER; if (doc) { PmmClearPSVI(doc); PmmInvalidatePSVI(doc); } vctxt = xmlRelaxNGNewValidCtxt( self ); if ( vctxt == NULL ) { CLEANUP_ERROR_HANDLER; REPORT_ERROR(0); croak( "cannot initialize the validation context" ); } #ifndef WITH_SERRORS /* Register Error callbacks */ xmlRelaxNGSetValidErrors( vctxt, (xmlRelaxNGValidityErrorFunc)LibXML_error_handler_ctx, (xmlRelaxNGValidityWarningFunc)LibXML_error_handler_ctx, saved_error ); #endif /* WITH_SERRORS */ /* ** test only ** xmlRelaxNGSetValidErrors( vctxt, (xmlRelaxNGValidityErrorFunc)fprintf, (xmlRelaxNGValidityWarningFunc)fprintf, stderr ); */ RETVAL = xmlRelaxNGValidateDoc( vctxt, doc ); xmlRelaxNGFreeValidCtxt( vctxt ); CLEANUP_ERROR_HANDLER; REPORT_ERROR(0); if ( RETVAL == 1 ) { XSRETURN_UNDEF; } if ( RETVAL == -1 ) { croak( "API Error" ); XSRETURN_UNDEF; } OUTPUT: RETVAL MODULE = XML::LibXML PACKAGE = XML::LibXML::Schema void DESTROY( self ) xmlSchemaPtr self CODE: xmlSchemaFree( self ); xmlSchemaPtr parse_location( self, url ) char * url PREINIT: const char * CLASS = "XML::LibXML::Schema"; xmlSchemaParserCtxtPtr rngctxt = NULL; PREINIT_SAVED_ERROR CODE: INIT_ERROR_HANDLER; rngctxt = xmlSchemaNewParserCtxt( url ); if ( rngctxt == NULL ) { CLEANUP_ERROR_HANDLER; REPORT_ERROR(0); croak( "failed to initialize Schema parser" ); } /* Register Error callbacks */ xmlSchemaSetParserErrors( rngctxt, (xmlSchemaValidityErrorFunc)LibXML_error_handler_ctx, (xmlSchemaValidityWarningFunc)LibXML_error_handler_ctx, saved_error ); RETVAL = xmlSchemaParse( rngctxt ); xmlSchemaFreeParserCtxt( rngctxt ); CLEANUP_ERROR_HANDLER; REPORT_ERROR((RETVAL == NULL) ? 0 : 1); OUTPUT: RETVAL xmlSchemaPtr parse_buffer( self, perlstring ) SV * perlstring PREINIT: const char * CLASS = "XML::LibXML::Schema"; xmlSchemaParserCtxtPtr rngctxt = NULL; char * string = NULL; STRLEN len = 0; PREINIT_SAVED_ERROR INIT: string = SvPV( perlstring, len ); if ( string == NULL ) { croak( "cannot parse empty string" ); } CODE: INIT_ERROR_HANDLER; rngctxt = xmlSchemaNewMemParserCtxt( string,len ); if ( rngctxt == NULL ) { CLEANUP_ERROR_HANDLER; REPORT_ERROR(0); croak( "failed to initialize Schema parser" ); } /* Register Error callbacks */ xmlSchemaSetParserErrors( rngctxt, (xmlSchemaValidityErrorFunc)LibXML_error_handler_ctx, (xmlSchemaValidityWarningFunc)LibXML_error_handler_ctx, saved_error ); RETVAL = xmlSchemaParse( rngctxt ); xmlSchemaFreeParserCtxt( rngctxt ); CLEANUP_ERROR_HANDLER; REPORT_ERROR((RETVAL == NULL) ? 0 : 1); OUTPUT: RETVAL int validate( self, node ) xmlSchemaPtr self xmlNodePtr node PREINIT: xmlSchemaValidCtxtPtr vctxt = NULL; PREINIT_SAVED_ERROR CODE: INIT_ERROR_HANDLER; if (node->type == XML_DOCUMENT_NODE) { PmmClearPSVI((xmlDocPtr)node); PmmInvalidatePSVI((xmlDocPtr)node); } vctxt = xmlSchemaNewValidCtxt( self ); if ( vctxt == NULL ) { CLEANUP_ERROR_HANDLER; REPORT_ERROR(0); croak( "cannot initialize the validation context" ); } /* Register Error callbacks */ xmlSchemaSetValidErrors( vctxt, (xmlSchemaValidityErrorFunc)LibXML_error_handler_ctx, (xmlSchemaValidityWarningFunc)LibXML_error_handler_ctx, saved_error ); if (node->type == XML_DOCUMENT_NODE) { RETVAL = xmlSchemaValidateDoc(vctxt, (xmlDocPtr)node); } else { RETVAL = xmlSchemaValidateOneElement(vctxt, node); } xmlSchemaFreeValidCtxt( vctxt ); CLEANUP_ERROR_HANDLER; REPORT_ERROR(0); if ( RETVAL > 0 ) { XSRETURN_UNDEF; } if ( RETVAL == -1 ) { croak( "API Error" ); XSRETURN_UNDEF; } OUTPUT: RETVAL #endif /* HAVE_SCHEMAS */ MODULE = XML::LibXML::XPathContext PACKAGE = XML::LibXML::XPathContext # PROTOTYPES: DISABLE SV* new( CLASS, ... ) const char * CLASS PREINIT: SV * pnode = &PL_sv_undef; INIT: xmlXPathContextPtr ctxt; CODE: if( items > 1 ) pnode = ST(1); ctxt = xmlXPathNewContext( NULL ); ctxt->namespaces = NULL; New(0, ctxt->user, sizeof(XPathContextData), XPathContextData); if (ctxt->user == NULL) { croak("XPathContext: failed to allocate proxy object\n"); } if (SvOK(pnode)) { XPathContextDATA(ctxt)->node = newSVsv(pnode); } else { XPathContextDATA(ctxt)->node = &PL_sv_undef; } XPathContextDATA(ctxt)->pool = NULL; XPathContextDATA(ctxt)->varLookup = NULL; XPathContextDATA(ctxt)->varData = NULL; xmlXPathRegisterFunc(ctxt, (const xmlChar *) "document", perlDocumentFunction); RETVAL = NEWSV(0,0), RETVAL = sv_setref_pv( RETVAL, CLASS, (void*)ctxt ); OUTPUT: RETVAL void DESTROY( self ) SV * self INIT: xmlXPathContextPtr ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(self))); CODE: xs_warn( "DESTROY XPATH CONTEXT" ); if (ctxt) { if (XPathContextDATA(ctxt) != NULL) { if (XPathContextDATA(ctxt)->node != NULL && SvOK(XPathContextDATA(ctxt)->node)) { SvREFCNT_dec(XPathContextDATA(ctxt)->node); } if (XPathContextDATA(ctxt)->varLookup != NULL && SvOK(XPathContextDATA(ctxt)->varLookup)) { SvREFCNT_dec(XPathContextDATA(ctxt)->varLookup); } if (XPathContextDATA(ctxt)->varData != NULL && SvOK(XPathContextDATA(ctxt)->varData)) { SvREFCNT_dec(XPathContextDATA(ctxt)->varData); } if (XPathContextDATA(ctxt)->pool != NULL && SvOK(XPathContextDATA(ctxt)->pool)) { SvREFCNT_dec((SV *)XPathContextDATA(ctxt)->pool); } Safefree(XPathContextDATA(ctxt)); } if (ctxt->namespaces != NULL) { xmlFree( ctxt->namespaces ); } if (ctxt->funcLookupData != NULL && SvROK((SV*)ctxt->funcLookupData) && SvTYPE(SvRV((SV *)ctxt->funcLookupData)) == SVt_PVHV) { SvREFCNT_dec((SV *)ctxt->funcLookupData); } xmlXPathFreeContext(ctxt); } SV* getContextNode( self ) SV * self INIT: xmlXPathContextPtr ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(self))); if ( ctxt == NULL ) { croak("XPathContext: missing xpath context\n"); } CODE: if(XPathContextDATA(ctxt)->node != NULL) { RETVAL = newSVsv(XPathContextDATA(ctxt)->node); } else { RETVAL = &PL_sv_undef; } OUTPUT: RETVAL int getContextPosition( self ) SV * self INIT: xmlXPathContextPtr ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(self))); if ( ctxt == NULL ) { croak("XPathContext: missing xpath context\n"); } CODE: RETVAL = ctxt->proximityPosition; OUTPUT: RETVAL int getContextSize( self ) SV * self INIT: xmlXPathContextPtr ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(self))); if ( ctxt == NULL ) { croak("XPathContext: missing xpath context\n"); } CODE: RETVAL = ctxt->contextSize; OUTPUT: RETVAL void setContextNode( self , pnode ) SV * self SV * pnode INIT: xmlXPathContextPtr ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(self))); if ( ctxt == NULL ) { croak("XPathContext: missing xpath context\n"); } PPCODE: if (XPathContextDATA(ctxt)->node != NULL) { SvREFCNT_dec(XPathContextDATA(ctxt)->node); } if (SvOK(pnode)) { XPathContextDATA(ctxt)->node = newSVsv(pnode); } else { XPathContextDATA(ctxt)->node = NULL; } void setContextPosition( self , position ) SV * self int position INIT: xmlXPathContextPtr ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(self))); if ( ctxt == NULL ) croak("XPathContext: missing xpath context\n"); if ( position < -1 || position > ctxt->contextSize ) croak("XPathContext: invalid position\n"); PPCODE: ctxt->proximityPosition = position; void setContextSize( self , size ) SV * self int size INIT: xmlXPathContextPtr ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(self))); if ( ctxt == NULL ) croak("XPathContext: missing xpath context\n"); if ( size < -1 ) croak("XPathContext: invalid size\n"); PPCODE: ctxt->contextSize = size; if ( size == 0 ) ctxt->proximityPosition = 0; else if ( size > 0 ) ctxt->proximityPosition = 1; else ctxt->proximityPosition = -1; void registerNs( pxpath_context, prefix, ns_uri ) SV * pxpath_context SV * prefix SV * ns_uri PREINIT: xmlXPathContextPtr ctxt = NULL; INIT: ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(pxpath_context))); if ( ctxt == NULL ) { croak("XPathContext: missing xpath context\n"); } LibXML_configure_xpathcontext(ctxt); PPCODE: if(SvOK(ns_uri)) { if(xmlXPathRegisterNs(ctxt, (xmlChar *) SvPV_nolen(prefix), (xmlChar *) SvPV_nolen(ns_uri)) == -1) { croak("XPathContext: cannot register namespace\n"); } } else { if(xmlXPathRegisterNs(ctxt, (xmlChar *) SvPV_nolen(prefix), NULL) == -1) { croak("XPathContext: cannot unregister namespace\n"); } } SV* lookupNs( pxpath_context, prefix ) SV * pxpath_context SV * prefix PREINIT: xmlXPathContextPtr ctxt = NULL; INIT: ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(pxpath_context))); if ( ctxt == NULL ) { croak("XPathContext: missing xpath context\n"); } LibXML_configure_xpathcontext(ctxt); CODE: RETVAL = C2Sv(xmlXPathNsLookup(ctxt, (xmlChar *) SvPV_nolen(prefix)), NULL); OUTPUT: RETVAL SV* getVarLookupData( self ) SV * self INIT: xmlXPathContextPtr ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(self))); if ( ctxt == NULL ) { croak("XPathContext: missing xpath context\n"); } CODE: if(XPathContextDATA(ctxt)->varData != NULL) { RETVAL = newSVsv(XPathContextDATA(ctxt)->varData); } else { RETVAL = &PL_sv_undef; } OUTPUT: RETVAL SV* getVarLookupFunc( self ) SV * self INIT: xmlXPathContextPtr ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(self))); if ( ctxt == NULL ) { croak("XPathContext: missing xpath context\n"); } CODE: if(XPathContextDATA(ctxt)->varData != NULL) { RETVAL = newSVsv(XPathContextDATA(ctxt)->varLookup); } else { RETVAL = &PL_sv_undef; } OUTPUT: RETVAL void registerVarLookupFunc( pxpath_context, lookup_func, lookup_data ) SV * pxpath_context SV * lookup_func SV * lookup_data PREINIT: xmlXPathContextPtr ctxt = NULL; XPathContextDataPtr data = NULL; INIT: ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(pxpath_context))); if ( ctxt == NULL ) croak("XPathContext: missing xpath context\n"); data = XPathContextDATA(ctxt); if ( data == NULL ) croak("XPathContext: missing xpath context private data\n"); LibXML_configure_xpathcontext(ctxt); /* free previous lookup function and data */ if (data->varLookup && SvOK(data->varLookup)) SvREFCNT_dec(data->varLookup); if (data->varData && SvOK(data->varData)) SvREFCNT_dec(data->varData); data->varLookup=NULL; data->varData=NULL; PPCODE: if (SvOK(lookup_func)) { if ( SvROK(lookup_func) && SvTYPE(SvRV(lookup_func)) == SVt_PVCV ) { data->varLookup = newSVsv(lookup_func); if (SvOK(lookup_data)) data->varData = newSVsv(lookup_data); xmlXPathRegisterVariableLookup(ctxt, LibXML_generic_variable_lookup, ctxt); if (ctxt->varLookupData==NULL || ctxt->varLookupData != ctxt) { croak( "XPathContext: registration failure\n" ); } } else { croak("XPathContext: 1st argument is not a CODE reference\n"); } } else { /* unregister */ xmlXPathRegisterVariableLookup(ctxt, NULL, NULL); } void registerFunctionNS( pxpath_context, name, uri, func) SV * pxpath_context char * name SV * uri SV * func PREINIT: xmlXPathContextPtr ctxt = NULL; SV * pfdr; SV * key; STRLEN len; char *strkey; INIT: ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(pxpath_context))); if ( ctxt == NULL ) { croak("XPathContext: missing xpath context\n"); } LibXML_configure_xpathcontext(ctxt); if ( !SvOK(func) || (SvOK(func) && ((SvROK(func) && SvTYPE(SvRV(func)) == SVt_PVCV ) || SvPOK(func)))) { if (ctxt->funcLookupData == NULL) { if (SvOK(func)) { pfdr = newRV_noinc((SV*) newHV()); ctxt->funcLookupData = pfdr; } else { /* looks like no perl function was never registered, */ /* nothing to unregister */ warn("XPathContext: nothing to unregister\n"); return; } } else { if (SvTYPE(SvRV((SV *)ctxt->funcLookupData)) == SVt_PVHV) { /* good, it's a HV */ pfdr = (SV *)ctxt->funcLookupData; } else { croak ("XPathContext: cannot register: funcLookupData structure occupied\n"); } } key = newSVpvn("",0); if (SvOK(uri)) { sv_catpv(key, "{"); sv_catsv(key, uri); sv_catpv(key, "}"); } sv_catpv(key, (const char*)name); strkey = SvPV(key, len); /* warn("Trying to store function '%s' in %d\n", strkey, pfdr); */ if (SvOK(func)) { (void) hv_store((HV *)SvRV(pfdr),strkey, len, newSVsv(func), 0); } else { /* unregister */ (void) hv_delete((HV *)SvRV(pfdr),strkey, len, G_DISCARD); } SvREFCNT_dec(key); } else { croak("XPathContext: 3rd argument is not a CODE reference or function name\n"); } PPCODE: if (SvOK(uri)) { xmlXPathRegisterFuncNS(ctxt, (xmlChar *) name, (xmlChar *) SvPV(uri, len), (SvOK(func) ? LibXML_generic_extension_function : NULL)); } else { xmlXPathRegisterFunc(ctxt, (xmlChar *) name, (SvOK(func) ? LibXML_generic_extension_function : NULL)); } void _free_node_pool( pxpath_context ) SV * pxpath_context PREINIT: xmlXPathContextPtr ctxt = NULL; INIT: ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(pxpath_context))); if ( ctxt == NULL ) { croak("XPathContext: missing xpath context\n"); } PPCODE: if (XPathContextDATA(ctxt)->pool != NULL) { SvREFCNT_dec((SV *)XPathContextDATA(ctxt)->pool); XPathContextDATA(ctxt)->pool = NULL; } void _findnodes( pxpath_context, perl_xpath ) SV * pxpath_context SV * perl_xpath PREINIT: xmlXPathContextPtr ctxt = NULL; ProxyNodePtr owner = NULL; xmlXPathObjectPtr found = NULL; xmlNodeSetPtr nodelist = NULL; SV * element = NULL ; xmlChar * xpath = NULL; xmlXPathCompExprPtr comp = NULL; PREINIT_SAVED_ERROR INIT: ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(pxpath_context))); if ( ctxt == NULL ) { croak("XPathContext: missing xpath context\n"); } LibXML_configure_xpathcontext(ctxt); if ( ctxt->node == NULL ) { croak("XPathContext: lost current node\n"); } if (sv_isobject(perl_xpath) && sv_isa(perl_xpath,"XML::LibXML::XPathExpression")) { comp = INT2PTR(xmlXPathCompExprPtr,SvIV((SV*)SvRV( perl_xpath ))); if (!comp) XSRETURN_UNDEF; } else { xpath = nodeSv2C(perl_xpath, ctxt->node); if ( !(xpath && xmlStrlen(xpath)) ) { if ( xpath ) xmlFree(xpath); croak("XPathContext: empty XPath found\n"); XSRETURN_UNDEF; } } PPCODE: INIT_ERROR_HANDLER; PUTBACK ; if (comp) { found = domXPathCompFindCtxt( ctxt, comp, 0 ); } else { found = domXPathFindCtxt( ctxt, xpath, 0 ); xmlFree(xpath); } SPAGAIN ; if (found != NULL) { nodelist = found->nodesetval; } else { nodelist = NULL; } CLEANUP_ERROR_HANDLER; if ( nodelist ) { REPORT_ERROR(1); if ( nodelist->nodeNr > 0 ) { int i; const char * cls = "XML::LibXML::Node"; xmlNodePtr tnode; int l = nodelist->nodeNr; for( i = 0 ; i < l; i++){ /* we have to create a new instance of an objectptr. * and then place the current node into the new object. * afterwards we can push the object to the array! */ element = NULL; tnode = nodelist->nodeTab[i]; if (tnode->type == XML_NAMESPACE_DECL) { xmlNsPtr newns = xmlCopyNamespace((xmlNsPtr)tnode); if ( newns != NULL ) { element = NEWSV(0,0); cls = PmmNodeTypeName( tnode ); element = sv_setref_pv( element, (const char *)cls, newns ); } else { continue; } } else { if (tnode->doc) { owner = PmmOWNERPO(PmmNewNode((xmlNodePtr) tnode->doc)); } else { /* we try to find a known node on the ancestor axis */ xmlNodePtr n = tnode; while (n && n->_private == NULL) n = n->parent; if (n) owner = PmmOWNERPO(((ProxyNodePtr)n->_private)); else owner = NULL; /* self contained node */ } element = PmmNodeToSv(tnode, owner); } XPUSHs( sv_2mortal(element) ); } } /* prevent libxml2 from freeing the actual nodes */ if (found->boolval) found->boolval=0; xmlXPathFreeObject(found); } else { xmlXPathFreeObject(found); REPORT_ERROR(0); } void _find( pxpath_context, pxpath, to_bool ) SV * pxpath_context SV * pxpath int to_bool PREINIT: xmlXPathContextPtr ctxt = NULL; ProxyNodePtr owner = NULL; xmlXPathObjectPtr found = NULL; xmlNodeSetPtr nodelist = NULL; xmlChar * xpath = NULL; xmlXPathCompExprPtr comp = NULL; PREINIT_SAVED_ERROR INIT: ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(pxpath_context))); if ( ctxt == NULL ) { croak("XPathContext: missing xpath context\n"); } LibXML_configure_xpathcontext(ctxt); if ( ctxt->node == NULL ) { croak("XPathContext: lost current node\n"); } if (sv_isobject(pxpath) && sv_isa(pxpath,"XML::LibXML::XPathExpression")) { comp = INT2PTR(xmlXPathCompExprPtr,SvIV((SV*)SvRV( pxpath ))); if (!comp) XSRETURN_UNDEF; } else { xpath = nodeSv2C(pxpath, ctxt->node); if ( !(xpath && xmlStrlen(xpath)) ) { if ( xpath ) xmlFree(xpath); croak("XPathContext: empty XPath found\n"); XSRETURN_UNDEF; } } PPCODE: INIT_ERROR_HANDLER; PUTBACK ; if (comp) { found = domXPathCompFindCtxt( ctxt, comp, to_bool ); } else { found = domXPathFindCtxt( ctxt, xpath, to_bool ); xmlFree(xpath); } SPAGAIN ; CLEANUP_ERROR_HANDLER; if (found) { REPORT_ERROR(1); switch (found->type) { case XPATH_NODESET: /* return as a NodeList */ /* access ->nodesetval */ XPUSHs(sv_2mortal(newSVpv("XML::LibXML::NodeList", 0))); nodelist = found->nodesetval; if ( nodelist ) { if ( nodelist->nodeNr > 0 ) { int i; const char * cls = "XML::LibXML::Node"; xmlNodePtr tnode; SV * element; int l = nodelist->nodeNr; for( i = 0 ; i < l; i++){ /* we have to create a new instance of an * objectptr. and then * place the current node into the new * object. afterwards we can * push the object to the array! */ tnode = nodelist->nodeTab[i]; /* let's be paranoid */ if (tnode->type == XML_NAMESPACE_DECL) { xmlNsPtr newns = xmlCopyNamespace((xmlNsPtr)tnode); if ( newns != NULL ) { element = NEWSV(0,0); cls = PmmNodeTypeName( tnode ); element = sv_setref_pv( element, (const char *)cls, (void*)newns ); } else { continue; } } else { if (tnode->doc) { owner = PmmOWNERPO(PmmNewNode((xmlNodePtr) tnode->doc)); } else { /* we try to find a known node on the ancestor axis */ xmlNodePtr n = tnode; while (n && n->_private == NULL) n = n->parent; if (n) owner = PmmOWNERPO(((ProxyNodePtr)n->_private)); else owner = NULL; /* self contained node */ } element = PmmNodeToSv(tnode, owner); } XPUSHs( sv_2mortal(element) ); } } } /* prevent libxml2 from freeing the actual nodes */ if (found->boolval) found->boolval=0; break; case XPATH_BOOLEAN: /* return as a Boolean */ /* access ->boolval */ XPUSHs(sv_2mortal(newSVpv("XML::LibXML::Boolean", 0))); XPUSHs(sv_2mortal(newSViv(found->boolval))); break; case XPATH_NUMBER: /* return as a Number */ /* access ->floatval */ XPUSHs(sv_2mortal(newSVpv("XML::LibXML::Number", 0))); XPUSHs(sv_2mortal(newSVnv(found->floatval))); break; case XPATH_STRING: /* access ->stringval */ /* return as a Literal */ XPUSHs(sv_2mortal(newSVpv("XML::LibXML::Literal", 0))); XPUSHs(sv_2mortal(C2Sv(found->stringval, NULL))); break; default: croak("Unknown XPath return type"); } xmlXPathFreeObject(found); } else { REPORT_ERROR(0); } MODULE = XML::LibXML PACKAGE = XML::LibXML::InputCallback void lib_cleanup_callbacks( self ) CODE: xmlCleanupInputCallbacks(); xmlRegisterDefaultInputCallbacks(); void lib_init_callbacks( self ) CODE: xmlRegisterDefaultInputCallbacks(); /* important */ xmlRegisterInputCallbacks((xmlInputMatchCallback) LibXML_input_match, (xmlInputOpenCallback) LibXML_input_open, (xmlInputReadCallback) LibXML_input_read, (xmlInputCloseCallback) LibXML_input_close); #ifdef HAVE_READER_SUPPORT MODULE = XML::LibXML PACKAGE = XML::LibXML::Reader xmlTextReaderPtr _newForFile(CLASS, filename, encoding, options) const char* CLASS const char* filename const char * encoding = SvOK($arg) ? SvPV_nolen($arg) : NULL; int options = SvOK($arg) ? SvIV($arg) : 0; CODE: RETVAL = xmlReaderForFile(filename, encoding, options); INIT_READER_ERROR_HANDLER(RETVAL); OUTPUT: RETVAL xmlTextReaderPtr _newForIO(CLASS, fh, url, encoding, options) const char* CLASS SV * fh const char * url = SvOK($arg) ? SvPV_nolen($arg) : NULL; const char * encoding = SvOK($arg) ? SvPV_nolen($arg) : NULL; int options = SvOK($arg) ? SvIV($arg) : 0; CODE: (void)SvREFCNT_inc(fh); /* _dec'd by LibXML_close_perl */ RETVAL = xmlReaderForIO((xmlInputReadCallback) LibXML_read_perl, (xmlInputCloseCallback) LibXML_close_perl, (void *) fh, url, encoding, options); INIT_READER_ERROR_HANDLER(RETVAL) OUTPUT: RETVAL xmlTextReaderPtr _newForString(CLASS, string, url, encoding, options) const char* CLASS SV * string const char * url = SvOK($arg) ? SvPV_nolen($arg) : NULL; const char * encoding = SvOK($arg) ? SvPV_nolen($arg) : NULL; int options = SvOK($arg) ? SvIV($arg) : 0; CODE: if (encoding == NULL && SvUTF8( string )) { encoding = "UTF-8"; } RETVAL = xmlReaderForDoc((xmlChar* )SvPV_nolen(string), url, encoding, options); INIT_READER_ERROR_HANDLER(RETVAL) OUTPUT: RETVAL xmlTextReaderPtr _newForFd(CLASS, fd, url, encoding, options) const char* CLASS int fd const char * url = SvOK($arg) ? SvPV_nolen($arg) : NULL; const char * encoding = SvOK($arg) ? SvPV_nolen($arg) : NULL; int options = SvOK($arg) ? SvIV($arg) : 0; CODE: RETVAL = xmlReaderForFd(fd, url, encoding, options); INIT_READER_ERROR_HANDLER(RETVAL) OUTPUT: RETVAL xmlTextReaderPtr _newForDOM(CLASS, perl_doc) const char* CLASS SV * perl_doc CODE: PmmREFCNT_inc(SvPROXYNODE(perl_doc)); /* _dec in DESTROY */ RETVAL = xmlReaderWalker((xmlDocPtr) PmmSvNode(perl_doc)); OUTPUT: RETVAL int attributeCount(reader) xmlTextReaderPtr reader CODE: RETVAL = xmlTextReaderAttributeCount(reader); OUTPUT: RETVAL SV * baseURI(reader) xmlTextReaderPtr reader PREINIT: const xmlChar *result = NULL; CODE: result = xmlTextReaderConstBaseUri(reader); RETVAL = C2Sv(result, NULL); OUTPUT: RETVAL long byteConsumed(reader) xmlTextReaderPtr reader CODE: RETVAL = xmlTextReaderByteConsumed(reader); OUTPUT: RETVAL int _close(reader) xmlTextReaderPtr reader CODE: RETVAL = xmlTextReaderClose(reader); OUTPUT: RETVAL SV * encoding(reader) xmlTextReaderPtr reader PREINIT: const xmlChar *result = NULL; CODE: result = xmlTextReaderConstEncoding(reader); RETVAL = C2Sv(result, NULL); OUTPUT: RETVAL SV * localName(reader) xmlTextReaderPtr reader PREINIT: const xmlChar *result = NULL; CODE: result = xmlTextReaderConstLocalName(reader); RETVAL = C2Sv(result, NULL); OUTPUT: RETVAL SV * name(reader) xmlTextReaderPtr reader PREINIT: const xmlChar *result = NULL; CODE: result = xmlTextReaderConstName(reader); RETVAL = C2Sv(result, NULL); OUTPUT: RETVAL SV * namespaceURI(reader) xmlTextReaderPtr reader PREINIT: const xmlChar *result = NULL; CODE: result = xmlTextReaderConstNamespaceUri(reader); RETVAL = C2Sv(result, NULL); OUTPUT: RETVAL SV * prefix(reader) xmlTextReaderPtr reader PREINIT: const xmlChar *result = NULL; CODE: result = xmlTextReaderConstPrefix(reader); RETVAL = C2Sv(result, NULL); OUTPUT: RETVAL SV * value(reader) xmlTextReaderPtr reader PREINIT: const xmlChar *result = NULL; CODE: result = xmlTextReaderConstValue(reader); RETVAL = C2Sv(result, NULL); OUTPUT: RETVAL SV * xmlLang(reader) xmlTextReaderPtr reader PREINIT: const xmlChar *result = NULL; CODE: result = xmlTextReaderConstXmlLang(reader); RETVAL = C2Sv(result, NULL); OUTPUT: RETVAL SV * xmlVersion(reader) xmlTextReaderPtr reader PREINIT: const xmlChar *result = NULL; CODE: result = xmlTextReaderConstXmlVersion(reader); RETVAL = C2Sv(result, NULL); OUTPUT: RETVAL int depth(reader) xmlTextReaderPtr reader CODE: RETVAL = xmlTextReaderDepth(reader); OUTPUT: RETVAL SV * getAttribute(reader, name) xmlTextReaderPtr reader char * name PREINIT: xmlChar *result = NULL; CODE: result = xmlTextReaderGetAttribute(reader, (xmlChar*) name); RETVAL = C2Sv(result, NULL); xmlFree(result); OUTPUT: RETVAL SV * getAttributeNo(reader, no) xmlTextReaderPtr reader int no PREINIT: xmlChar *result = NULL; CODE: result = xmlTextReaderGetAttributeNo(reader, no); RETVAL = C2Sv(result, NULL); xmlFree(result); OUTPUT: RETVAL SV * getAttributeNs(reader, localName, namespaceURI) xmlTextReaderPtr reader char * localName char * namespaceURI = SvOK($arg) ? SvPV_nolen($arg) : NULL; PREINIT: xmlChar *result = NULL; CODE: result = xmlTextReaderGetAttributeNs(reader, (xmlChar*) localName, (xmlChar*) namespaceURI); RETVAL = C2Sv(result, NULL); xmlFree(result); OUTPUT: RETVAL int columnNumber(reader) xmlTextReaderPtr reader CODE: RETVAL = xmlTextReaderGetParserColumnNumber(reader); OUTPUT: RETVAL int lineNumber(reader) xmlTextReaderPtr reader CODE: RETVAL = xmlTextReaderGetParserLineNumber(reader); OUTPUT: RETVAL int _getParserProp(reader, prop) xmlTextReaderPtr reader int prop CODE: RETVAL = xmlTextReaderGetParserProp(reader, prop); OUTPUT: RETVAL int hasAttributes(reader) xmlTextReaderPtr reader CODE: RETVAL = xmlTextReaderHasAttributes(reader); OUTPUT: RETVAL int hasValue(reader) xmlTextReaderPtr reader CODE: RETVAL = xmlTextReaderHasValue(reader); OUTPUT: RETVAL SV* getAttributeHash(reader) xmlTextReaderPtr reader PREINIT: HV* hv; SV* sv; const xmlChar* name; PREINIT_SAVED_ERROR CODE: INIT_ERROR_HANDLER; hv=newHV(); if (xmlTextReaderHasAttributes(reader) && xmlTextReaderMoveToFirstAttribute(reader)==1) { do { name = xmlTextReaderConstName(reader); sv=C2Sv((xmlTextReaderConstValue(reader)),NULL); if (sv && hv_store(hv, (const char*) name, xmlStrlen(name), sv, 0)==NULL) { SvREFCNT_dec(sv); /* free if not needed by hv_stores */ } } while (xmlTextReaderMoveToNextAttribute(reader)==1); xmlTextReaderMoveToElement(reader); } RETVAL=newRV_noinc((SV*)hv); CLEANUP_ERROR_HANDLER; REPORT_ERROR(0); OUTPUT: RETVAL int isDefault(reader) xmlTextReaderPtr reader CODE: RETVAL = xmlTextReaderIsDefault(reader); OUTPUT: RETVAL int isEmptyElement(reader) xmlTextReaderPtr reader CODE: RETVAL = xmlTextReaderIsEmptyElement(reader); OUTPUT: RETVAL int isNamespaceDecl(reader) xmlTextReaderPtr reader CODE: RETVAL = xmlTextReaderIsNamespaceDecl(reader); OUTPUT: RETVAL int isValid(reader) xmlTextReaderPtr reader CODE: RETVAL = xmlTextReaderIsValid(reader); OUTPUT: RETVAL SV * lookupNamespace(reader, prefix) xmlTextReaderPtr reader char * prefix = SvOK($arg) ? SvPV_nolen($arg) : NULL; PREINIT: xmlChar *result = NULL; CODE: result = xmlTextReaderLookupNamespace(reader, (xmlChar*) prefix); RETVAL = C2Sv(result, NULL); xmlFree(result); OUTPUT: RETVAL int moveToAttribute(reader, name) xmlTextReaderPtr reader char * name CODE: RETVAL = xmlTextReaderMoveToAttribute(reader, (xmlChar*) name); OUTPUT: RETVAL int moveToAttributeNo(reader, no) xmlTextReaderPtr reader int no CODE: RETVAL = xmlTextReaderMoveToAttributeNo(reader, no); OUTPUT: RETVAL int moveToAttributeNs(reader, localName, namespaceURI) xmlTextReaderPtr reader char * localName char * namespaceURI = SvOK($arg) ? SvPV_nolen($arg) : NULL; CODE: RETVAL = xmlTextReaderMoveToAttributeNs(reader, (xmlChar*) localName, (xmlChar*) namespaceURI); OUTPUT: RETVAL int moveToElement(reader) xmlTextReaderPtr reader CODE: RETVAL = xmlTextReaderMoveToElement(reader); OUTPUT: RETVAL int moveToFirstAttribute(reader) xmlTextReaderPtr reader CODE: RETVAL = xmlTextReaderMoveToFirstAttribute(reader); OUTPUT: RETVAL int moveToNextAttribute(reader) xmlTextReaderPtr reader CODE: RETVAL = xmlTextReaderMoveToNextAttribute(reader); OUTPUT: RETVAL int next(reader) xmlTextReaderPtr reader PREINIT: PREINIT_SAVED_ERROR CODE: INIT_ERROR_HANDLER; RETVAL = xmlTextReaderNext(reader); CLEANUP_ERROR_HANDLER; REPORT_ERROR(0); OUTPUT: RETVAL #define LIBXML_READER_NEXT_SIBLING(ret,reader) \ ret = xmlTextReaderNextSibling(reader); \ if (ret == -1) \ { \ int depth; \ depth = xmlTextReaderDepth(reader); \ ret = xmlTextReaderRead(reader); \ while (ret == 1 && xmlTextReaderDepth(reader) > depth) { \ ret = xmlTextReaderNext(reader); \ } \ if (ret == 1) { \ if (xmlTextReaderDepth(reader) != depth) { \ ret = 0; \ } else if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_END_ELEMENT) { \ ret = xmlTextReaderRead(reader); \ } \ } \ } int nextSibling(reader) xmlTextReaderPtr reader PREINIT: PREINIT_SAVED_ERROR CODE: INIT_ERROR_HANDLER; LIBXML_READER_NEXT_SIBLING(RETVAL,reader) CLEANUP_ERROR_HANDLER; REPORT_ERROR(0); OUTPUT: RETVAL int nextSiblingElement(reader, name = NULL, nsURI = NULL) xmlTextReaderPtr reader const char * name const char * nsURI PREINIT: PREINIT_SAVED_ERROR CODE: INIT_ERROR_HANDLER; do { LIBXML_READER_NEXT_SIBLING(RETVAL,reader) if (LIBXML_READER_TEST_ELEMENT(reader,name,nsURI)) { break; } } while (RETVAL == 1); CLEANUP_ERROR_HANDLER; REPORT_ERROR(0); OUTPUT: RETVAL int nextElement(reader, name = NULL, nsURI = NULL) xmlTextReaderPtr reader const char * name const char * nsURI PREINIT: PREINIT_SAVED_ERROR CODE: INIT_ERROR_HANDLER; do { RETVAL = xmlTextReaderRead(reader); if (LIBXML_READER_TEST_ELEMENT(reader,name,nsURI)) { break; } } while (RETVAL == 1); CLEANUP_ERROR_HANDLER; REPORT_ERROR(0); OUTPUT: RETVAL int nextPatternMatch(reader, compiled) xmlTextReaderPtr reader xmlPatternPtr compiled PREINIT: PREINIT_SAVED_ERROR xmlNodePtr node = NULL; CODE: if ( compiled == NULL ) croak("Usage: $reader->nextPatternMatch( a-XML::LibXML::Pattern-object )"); do { RETVAL = xmlTextReaderRead(reader); node = xmlTextReaderCurrentNode(reader); if (node && xmlPatternMatch(compiled, node)) { break; } } while (RETVAL == 1); CLEANUP_ERROR_HANDLER; REPORT_ERROR(0); OUTPUT: RETVAL int skipSiblings(reader) xmlTextReaderPtr reader PREINIT: int depth; PREINIT: PREINIT_SAVED_ERROR CODE: INIT_ERROR_HANDLER; depth = xmlTextReaderDepth(reader); RETVAL = -1; if (depth > 0) { do { RETVAL = xmlTextReaderNext(reader); } while (RETVAL == 1 && xmlTextReaderDepth(reader) >= depth); if (xmlTextReaderNodeType(reader) != XML_READER_TYPE_END_ELEMENT) { RETVAL = -1; } } CLEANUP_ERROR_HANDLER; REPORT_ERROR(0); OUTPUT: RETVAL int nodeType(reader) xmlTextReaderPtr reader CODE: RETVAL = xmlTextReaderNodeType(reader); OUTPUT: RETVAL SV* quoteChar(reader) xmlTextReaderPtr reader PREINIT: int ret; CODE: ret = xmlTextReaderQuoteChar(reader); if (ret == -1) XSRETURN_UNDEF; RETVAL = newSVpvf("%c",ret); OUTPUT: RETVAL int read(reader) xmlTextReaderPtr reader PREINIT: PREINIT_SAVED_ERROR CODE: INIT_ERROR_HANDLER; RETVAL = xmlTextReaderRead(reader); CLEANUP_ERROR_HANDLER; REPORT_ERROR(0); OUTPUT: RETVAL int readAttributeValue(reader) xmlTextReaderPtr reader PREINIT: PREINIT_SAVED_ERROR CODE: INIT_ERROR_HANDLER; RETVAL = xmlTextReaderReadAttributeValue(reader); CLEANUP_ERROR_HANDLER; REPORT_ERROR(0); OUTPUT: RETVAL SV * readInnerXml(reader) xmlTextReaderPtr reader PREINIT: xmlChar *result = NULL; PREINIT: PREINIT_SAVED_ERROR CODE: INIT_ERROR_HANDLER; result = xmlTextReaderReadInnerXml(reader); CLEANUP_ERROR_HANDLER; REPORT_ERROR(0); if (!result) XSRETURN_UNDEF; RETVAL = C2Sv(result, NULL); xmlFree(result); OUTPUT: RETVAL SV * readOuterXml(reader) xmlTextReaderPtr reader PREINIT: xmlChar *result = NULL; PREINIT: PREINIT_SAVED_ERROR CODE: INIT_ERROR_HANDLER; result = xmlTextReaderReadOuterXml(reader); CLEANUP_ERROR_HANDLER; REPORT_ERROR(0); if (result) { RETVAL = C2Sv(result, NULL); xmlFree(result); } else { XSRETURN_UNDEF; } OUTPUT: RETVAL int readState(reader) xmlTextReaderPtr reader CODE: RETVAL = xmlTextReaderReadState(reader); OUTPUT: RETVAL int _setParserProp(reader, prop, value) xmlTextReaderPtr reader int prop int value CODE: RETVAL = xmlTextReaderSetParserProp(reader, prop, value); OUTPUT: RETVAL int standalone(reader) xmlTextReaderPtr reader CODE: RETVAL = xmlTextReaderStandalone(reader); OUTPUT: RETVAL SV * _nodePath(reader) xmlTextReaderPtr reader PREINIT: xmlNodePtr node = NULL; xmlChar * path = NULL; CODE: node = xmlTextReaderCurrentNode(reader); if ( node ==NULL ) { XSRETURN_UNDEF; } path = xmlGetNodePath( node ); if ( path == NULL ) { XSRETURN_UNDEF; } RETVAL = C2Sv(path,NULL); xmlFree(path); OUTPUT: RETVAL #ifdef LIBXML_PATTERN_ENABLED int matchesPattern(reader, compiled) xmlTextReaderPtr reader xmlPatternPtr compiled PREINIT: xmlNodePtr node = NULL; CODE: if ( compiled == NULL ) XSRETURN_UNDEF; node = xmlTextReaderCurrentNode(reader); if ( node ==NULL ) { XSRETURN_UNDEF; } RETVAL = xmlPatternMatch(compiled, node); OUTPUT: RETVAL #endif /* LIBXML_PATTERN_ENABLED */ SV * copyCurrentNode(reader,expand = 0) xmlTextReaderPtr reader int expand PREINIT: xmlNodePtr node = NULL; xmlNodePtr copy; xmlDocPtr doc = NULL; ProxyNodePtr proxy; PREINIT: PREINIT_SAVED_ERROR CODE: INIT_ERROR_HANDLER; if (expand) { node = xmlTextReaderExpand(reader); } else { node = xmlTextReaderCurrentNode(reader); } if (node) { doc = xmlTextReaderCurrentDoc(reader); } if (!doc) { CLEANUP_ERROR_HANDLER; REPORT_ERROR(0); XSRETURN_UNDEF; } if (xmlTextReaderGetParserProp(reader,XML_PARSER_VALIDATE)) PmmInvalidatePSVI(doc); /* the document may have psvi info */ copy = PmmCloneNode( node, expand ); if ( copy == NULL ) { CLEANUP_ERROR_HANDLER; REPORT_ERROR(0); XSRETURN_UNDEF; } if ( copy->type == XML_DTD_NODE ) { RETVAL = PmmNodeToSv(copy, NULL); } else { ProxyNodePtr docfrag = NULL; if ( doc != NULL ) { xmlSetTreeDoc(copy, doc); } proxy = PmmNewNode((xmlNodePtr)doc); if (PmmREFCNT(proxy) == 0) { PmmREFCNT_inc(proxy); } LibXML_set_reader_preserve_flag(reader); docfrag = PmmNewFragment( doc ); xmlAddChild( PmmNODE(docfrag), copy ); RETVAL = PmmNodeToSv(copy, docfrag); } CLEANUP_ERROR_HANDLER; REPORT_ERROR(0); OUTPUT: RETVAL SV * document(reader) xmlTextReaderPtr reader PREINIT: xmlDocPtr doc = NULL; CODE: doc = xmlTextReaderCurrentDoc(reader); if (!doc) XSRETURN_UNDEF; RETVAL = PmmNodeToSv((xmlNodePtr)doc, NULL); /* FIXME: taint the document with PmmInvalidatePSVI if the reader did validation */ if ( PmmREFCNT(SvPROXYNODE(RETVAL))==1 ) { /* will be decremented in Reader destructor */ PmmREFCNT_inc(SvPROXYNODE(RETVAL)); } if (xmlTextReaderGetParserProp(reader,XML_PARSER_VALIDATE)) PmmInvalidatePSVI(doc); /* the document may have psvi info */ LibXML_set_reader_preserve_flag(reader); OUTPUT: RETVAL int _preservePattern(reader,pattern,ns_map=NULL) xmlTextReaderPtr reader char * pattern AV * ns_map PREINIT: xmlChar** namespaces = NULL; SV** aux; int last,i; CODE: if (ns_map) { last = av_len(ns_map); New(0,namespaces, last+2, xmlChar*); for( i = 0; i <= last ; i++ ) { aux = av_fetch(ns_map,i,0); namespaces[i]=(xmlChar*) SvPV_nolen(*aux); } namespaces[i]=0; } RETVAL = xmlTextReaderPreservePattern(reader,(const xmlChar*) pattern, (const xmlChar**)namespaces); Safefree(namespaces); OUTPUT: RETVAL SV * preserveNode(reader) xmlTextReaderPtr reader PREINIT: xmlNodePtr node; xmlDocPtr doc; ProxyNodePtr proxy; PREINIT_SAVED_ERROR CODE: INIT_ERROR_HANDLER; doc = xmlTextReaderCurrentDoc(reader); if (!doc) { CLEANUP_ERROR_HANDLER; REPORT_ERROR(0); XSRETURN_UNDEF; } proxy = PmmNewNode((xmlNodePtr)doc); if ( PmmREFCNT(proxy) == 0 ) { /* new proxy node */ PmmREFCNT_inc(proxy); } LibXML_set_reader_preserve_flag(reader); node = xmlTextReaderPreserve(reader); CLEANUP_ERROR_HANDLER; REPORT_ERROR(0); if (node) { RETVAL = PmmNodeToSv(node, proxy); } else { XSRETURN_UNDEF; } OUTPUT: RETVAL int finish(reader) xmlTextReaderPtr reader PREINIT: PREINIT_SAVED_ERROR CODE: INIT_ERROR_HANDLER; while (1) { RETVAL = xmlTextReaderRead(reader); if (RETVAL!=1) break; } CLEANUP_ERROR_HANDLER; REPORT_ERROR(0); RETVAL++; /* we want 0 - fail, 1- success */ OUTPUT: RETVAL #ifdef HAVE_SCHEMAS int _setRelaxNGFile(reader,rng) xmlTextReaderPtr reader char* rng CODE: RETVAL = xmlTextReaderRelaxNGValidate(reader,rng); OUTPUT: RETVAL int _setRelaxNG(reader,rng_doc) xmlTextReaderPtr reader xmlRelaxNGPtr rng_doc CODE: RETVAL = xmlTextReaderRelaxNGSetSchema(reader,rng_doc); OUTPUT: RETVAL int _setXSDFile(reader,xsd) xmlTextReaderPtr reader char* xsd CODE: RETVAL = xmlTextReaderSchemaValidate(reader,xsd); OUTPUT: RETVAL int _setXSD(reader,xsd_doc) xmlTextReaderPtr reader xmlSchemaPtr xsd_doc CODE: RETVAL = xmlTextReaderSetSchema(reader,xsd_doc); OUTPUT: RETVAL #endif /* HAVE_SCHEMAS */ void _DESTROY(reader) xmlTextReaderPtr reader PREINIT: xmlDocPtr doc; ProxyNodePtr proxy; /* SV * error_sv = NULL; xmlTextReaderErrorFunc f = NULL; */ CODE: if ( LibXML_get_reader_preserve_flag(reader) ) { doc = xmlTextReaderCurrentDoc(reader); if (doc) { proxy = PmmNewNode((xmlNodePtr)doc); if ( PmmREFCNT(proxy) == 0 ) { PmmREFCNT_inc(proxy); } PmmREFCNT_dec(proxy); } } if (xmlTextReaderReadState(reader) != XML_TEXTREADER_MODE_CLOSED) { xmlTextReaderClose(reader); } /* xmlTextReaderGetErrorHandler(reader, &f, (void **) &error_sv); if (error_sv) { sv_2mortal(error_sv); } */ xmlFreeTextReader(reader); #endif /* HAVE_READER_SUPPORT */ #ifdef WITH_SERRORS MODULE = XML::LibXML PACKAGE = XML::LibXML::LibError int domain( self ) xmlErrorPtr self CODE: RETVAL = self->domain; OUTPUT: RETVAL int code( self ) xmlErrorPtr self CODE: RETVAL = self->code; OUTPUT: RETVAL int line( self ) xmlErrorPtr self CODE: RETVAL = self->line; OUTPUT: RETVAL int num1( self ) xmlErrorPtr self ALIAS: int1 = 1 CODE: PERL_UNUSED_VAR(ix); RETVAL = self->int1; OUTPUT: RETVAL int num2( self ) xmlErrorPtr self ALIAS: int2 = 1 CODE: PERL_UNUSED_VAR(ix); RETVAL = self->int2; OUTPUT: RETVAL int level( self ) xmlErrorPtr self CODE: RETVAL = (int)self->level; OUTPUT: RETVAL char * message( self ) xmlErrorPtr self CODE: RETVAL = self->message; OUTPUT: RETVAL char * file( self ) xmlErrorPtr self CODE: RETVAL = (char*)self->file; OUTPUT: RETVAL char * str1( self ) xmlErrorPtr self CODE: RETVAL = (char*)self->str1; OUTPUT: RETVAL char * str2( self ) xmlErrorPtr self CODE: RETVAL = (char*)self->str2; OUTPUT: RETVAL char * str3( self ) xmlErrorPtr self CODE: RETVAL = (char*)self->str3; OUTPUT: RETVAL void context_and_column( self ) xmlErrorPtr self PREINIT: xmlParserInputPtr input; const xmlChar *cur, *base, *col_cur; unsigned int n, col; /* GCC warns if signed, because compared with sizeof() */ xmlChar content[81]; /* space for 80 chars + line terminator */ xmlChar *ctnt; int domain; xmlParserCtxtPtr ctxt = NULL; PPCODE: domain = self->domain; if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) || (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) || (domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) { ctxt = (xmlParserCtxtPtr) self->ctxt; } if (ctxt == NULL) XSRETURN_EMPTY; input = ctxt->input; if ((input != NULL) && (input->filename == NULL) && (ctxt->inputNr > 1)) { input = ctxt->inputTab[ctxt->inputNr - 2]; } if (input == NULL) XSRETURN_EMPTY; cur = input->cur; base = input->base; /* skip backwards over any end-of-lines */ while ((cur > base) && ((*(cur) == '\n') || (*(cur) == '\r'))) { cur--; } n = 0; /* search backwards for beginning-of-line (to max buff size) */ while ((n++ < (sizeof(content)-1)) && (cur > base) && (*(cur) != '\n') && (*(cur) != '\r')) cur--; /* search backwards for beginning-of-line for calculating the * column. */ col_cur = cur; while ((col_cur > base) && (*(col_cur) != '\n') && (*(col_cur) != '\r')) col_cur--; if ((*(cur) == '\n') || (*(cur) == '\r')) cur++; if ((*(col_cur) == '\n') || (*(col_cur) == '\r')) col_cur++; /* calculate the error position in terms of the current position */ col = input->cur - col_cur; /* search forward for end-of-line (to max buff size) */ n = 0; ctnt = content; /* copy selected text to our buffer */ while ((*cur != 0) && (*(cur) != '\n') && (*(cur) != '\r') && (n < sizeof(content)-1)) { *ctnt++ = *cur++; n++; } *ctnt = 0; EXTEND(SP,2); PUSHs(sv_2mortal(C2Sv(content, NULL))); PUSHs(sv_2mortal(newSViv(col))); #endif /* WITH_SERRORS */ #ifdef LIBXML_PATTERN_ENABLED MODULE = XML::LibXML PACKAGE = XML::LibXML::Pattern xmlPatternPtr _compilePattern(CLASS, ppattern, pattern_type, ns_map=NULL) SV * ppattern AV * ns_map int pattern_type PREINIT: xmlChar * pattern = Sv2C(ppattern, NULL); xmlChar** namespaces = NULL; SV** aux; int last,i; PREINIT_SAVED_ERROR CODE: if ( pattern == NULL ) XSRETURN_UNDEF; if (ns_map) { last = av_len(ns_map); New(0,namespaces, last+2, xmlChar*); for( i = 0; i <= last ; i++ ) { aux = av_fetch(ns_map,i,0); namespaces[i]=(xmlChar*) SvPV_nolen(*aux); } namespaces[i]=0; } INIT_ERROR_HANDLER; RETVAL = xmlPatterncompile(pattern, NULL, pattern_type, (const xmlChar **) namespaces); Safefree(namespaces); xmlFree( pattern ); CLEANUP_ERROR_HANDLER; REPORT_ERROR(0); if ( RETVAL == NULL ) { croak("Compilation of pattern failed"); } OUTPUT: RETVAL int matchesNode(self, node) xmlPatternPtr self xmlNodePtr node CODE: if ( node ==NULL ) { XSRETURN_UNDEF; } RETVAL = xmlPatternMatch(self, node); OUTPUT: RETVAL void DESTROY( self ) xmlPatternPtr self CODE: xs_warn( "DESTROY PATTERN OBJECT" ); xmlFreePattern(self); #endif /* LIBXML_PATTERN_ENABLED */ #ifdef LIBXML_REGEXP_ENABLED MODULE = XML::LibXML PACKAGE = XML::LibXML::RegExp xmlRegexpPtr _compile(CLASS, pregexp) SV * pregexp PREINIT: xmlChar * regexp = Sv2C(pregexp, NULL); PREINIT_SAVED_ERROR CODE: if ( regexp == NULL ) XSRETURN_UNDEF; INIT_ERROR_HANDLER; RETVAL = xmlRegexpCompile(regexp); xmlFree( regexp ); CLEANUP_ERROR_HANDLER; REPORT_ERROR(0); if ( RETVAL == NULL ) { croak("Compilation of regexp failed"); } OUTPUT: RETVAL int matches(self, pvalue) xmlRegexpPtr self SV* pvalue PREINIT: xmlChar * value = Sv2C(pvalue, NULL); CODE: if ( value == NULL ) XSRETURN_UNDEF; RETVAL = xmlRegexpExec(self,value); xmlFree( value ); OUTPUT: RETVAL int isDeterministic(self) xmlRegexpPtr self CODE: RETVAL = xmlRegexpIsDeterminist(self); OUTPUT: RETVAL void DESTROY( self ) xmlRegexpPtr self CODE: xs_warn( "DESTROY REGEXP OBJECT" ); xmlRegFreeRegexp(self); #endif /* LIBXML_REGEXP_ENABLED */ MODULE = XML::LibXML PACKAGE = XML::LibXML::XPathExpression xmlXPathCompExprPtr new(CLASS, pxpath) SV * pxpath PREINIT: xmlChar * xpath = Sv2C(pxpath, NULL); PREINIT_SAVED_ERROR CODE: if ( pxpath == NULL ) XSRETURN_UNDEF; INIT_ERROR_HANDLER; RETVAL = xmlXPathCompile( xpath ); xmlFree( xpath ); CLEANUP_ERROR_HANDLER; REPORT_ERROR(0); if ( RETVAL == NULL ) { croak("Compilation of XPath expression failed!"); } OUTPUT: RETVAL void DESTROY( self ) xmlXPathCompExprPtr self CODE: xs_warn( "DESTROY COMPILED XPATH OBJECT" ); xmlXPathFreeCompExpr(self); MODULE = XML::LibXML PACKAGE = XML::LibXML::Common PROTOTYPES: DISABLE SV* encodeToUTF8( encoding, string ) const char * encoding SV * string PREINIT: xmlChar * realstring = NULL; xmlChar * tstr = NULL; xmlCharEncoding enc = 0; STRLEN len = 0; xmlBufferPtr in = NULL, out = NULL; xmlCharEncodingHandlerPtr coder = NULL; PREINIT_SAVED_ERROR CODE: if (!SvOK(string)) { XSRETURN_UNDEF; } else if (!SvCUR(string)) { XSRETURN_PV(""); } realstring = (xmlChar*) SvPV(string, len); if ( realstring != NULL ) { /* warn("encode %s", realstring ); */ #ifdef HAVE_UTF8 if ( !DO_UTF8(string) && encoding != NULL ) { #else if ( encoding != NULL ) { #endif enc = xmlParseCharEncoding( encoding ); if ( enc == 0 ) { /* this happens if the encoding is "" or NULL */ enc = XML_CHAR_ENCODING_UTF8; } if ( enc == XML_CHAR_ENCODING_UTF8 ) { /* copy the string */ /* warn( "simply copy the string" ); */ tstr = xmlStrndup( realstring, len ); } else { INIT_ERROR_HANDLER; if ( enc > 1 ) { coder= xmlGetCharEncodingHandler( enc ); } else if ( enc == XML_CHAR_ENCODING_ERROR ){ coder =xmlFindCharEncodingHandler( encoding ); } else { croak("no encoder found\n"); } if ( coder == NULL ) { croak( "cannot encode string" ); } in = xmlBufferCreateStatic((void*)realstring, len ); out = xmlBufferCreate(); if ( xmlCharEncInFunc( coder, out, in ) >= 0 ) { tstr = xmlStrdup( out->content ); } xmlBufferFree( in ); xmlBufferFree( out ); xmlCharEncCloseFunc( coder ); CLEANUP_ERROR_HANDLER; REPORT_ERROR(0); } } else { tstr = xmlStrndup( realstring, len ); } if ( !tstr ) { croak( "return value missing!" ); } len = xmlStrlen( tstr ); RETVAL = newSVpvn( (const char *)tstr, len ); #ifdef HAVE_UTF8 SvUTF8_on(RETVAL); #endif xmlFree(tstr); } else { XSRETURN_UNDEF; } OUTPUT: RETVAL SV* decodeFromUTF8( encoding, string ) const char * encoding SV* string PREINIT: xmlChar * tstr = NULL; xmlChar * realstring = NULL; xmlCharEncoding enc = 0; STRLEN len = 0; xmlBufferPtr in = NULL, out = NULL; xmlCharEncodingHandlerPtr coder = NULL; PREINIT_SAVED_ERROR CODE: #ifdef HAVE_UTF8 if ( !SvOK(string) ) { XSRETURN_UNDEF; } else if (!SvCUR(string)) { XSRETURN_PV(""); } else if ( !SvUTF8(string) ) { croak("string is not utf8!!"); } else { #endif realstring = (xmlChar*) SvPV(string, len); if ( realstring != NULL ) { /* warn("decode %s", realstring ); */ enc = xmlParseCharEncoding( encoding ); if ( enc == 0 ) { /* this happens if the encoding is "" or NULL */ enc = XML_CHAR_ENCODING_UTF8; } if ( enc == XML_CHAR_ENCODING_UTF8 ) { /* copy the string */ /* warn( "simply copy the string" ); */ tstr = xmlStrdup( realstring ); len = xmlStrlen( tstr ); } else { INIT_ERROR_HANDLER; if ( enc > 1 ) { coder= xmlGetCharEncodingHandler( enc ); } else if ( enc == XML_CHAR_ENCODING_ERROR ){ coder = xmlFindCharEncodingHandler( encoding ); } else { croak("no encoder found\n"); } if ( coder == NULL ) { croak( "cannot encode string" ); } in = xmlBufferCreate(); out = xmlBufferCreate(); xmlBufferCCat( in, (char*) realstring ); if ( xmlCharEncOutFunc( coder, out, in ) >= 0 ) { len = xmlBufferLength( out ); tstr = xmlCharStrndup( (char*) xmlBufferContent( out ), len ); } xmlBufferFree( in ); xmlBufferFree( out ); xmlCharEncCloseFunc( coder ); CLEANUP_ERROR_HANDLER; REPORT_ERROR(0); if ( !tstr ) { croak( "return value missing!" ); } } RETVAL = newSVpvn( (const char *)tstr, len ); xmlFree( tstr ); #ifdef HAVE_UTF8 if ( enc == XML_CHAR_ENCODING_UTF8 ) { SvUTF8_on(RETVAL); } #endif } else { XSRETURN_UNDEF; } #ifdef HAVE_UTF8 } #endif OUTPUT: RETVAL