|
From: Petr P. <pa...@us...> - 2003-03-16 16:21:32
|
Update of /cvsroot/perl-xml/XML-LibXML-XPathContext
In directory sc8-pr-cvs1:/tmp/cvs-serv27568
Modified Files:
XPathContext.xs XPathContext.pm
Log Message:
- added getContextNode and setContextNode
- XPathContext object now increments PmmREFCNT for ctx->node and ctx->doc
Index: XPathContext.xs
===================================================================
RCS file: /cvsroot/perl-xml/XML-LibXML-XPathContext/XPathContext.xs,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- XPathContext.xs 14 Mar 2003 17:20:47 -0000 1.4
+++ XPathContext.xs 16 Mar 2003 16:21:29 -0000 1.5
@@ -49,12 +49,12 @@
va_start(args, msg);
sv_vsetpvfn(sv, msg, strlen(msg), &args, NULL, 0, NULL);
va_end(args);
-
+
if (LibXML_error != NULL) {
sv_catsv(LibXML_error, sv); /* remember the last error */
}
else {
- croak("%s",SvPV(sv, PL_na));
+ croak("%s",SvPV(sv, PL_na));
}
SvREFCNT_dec(sv);
@@ -66,119 +66,119 @@
/* 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 *name,
const xmlChar *ns_uri)
{
- xmlXPathObjectPtr ret;
- SV * lookup_func;
- SV * lookup_data;
- I32 count;
- STRLEN n_a;
- SV * perl_result;
- AV * array_result;
- xmlNodePtr tmp_node, tmp_node1;
- dSP;
- char * tmp_string;
- double tmp_double;
- int tmp_int;
- SV * data;
+ xmlXPathObjectPtr ret;
+ SV * lookup_func;
+ SV * lookup_data;
+ I32 count;
+ STRLEN n_a;
+ SV * perl_result;
+ AV * array_result;
+ xmlNodePtr tmp_node, tmp_node1;
+ dSP;
+ char * tmp_string;
+ double tmp_double;
+ int tmp_int;
+ SV * data;
- data = (SV *) varLookupData;
- if (varLookupData == NULL || !SvROK(data) ||
- SvTYPE(SvRV(data)) != SVt_PVAV) {
- croak("XPathContext: lost variable lookup data structure!\n");
- }
+ data = (SV *) varLookupData;
+ if (varLookupData == NULL || !SvROK(data) ||
+ SvTYPE(SvRV(data)) != SVt_PVAV) {
+ croak("XPathContext: lost variable lookup data structure!\n");
+ }
- lookup_func = *(av_fetch((AV *) SvRV(data),0,0 ));
- lookup_data = *(av_fetch((AV *) SvRV(data),1,0 ));
+ lookup_func = *(av_fetch((AV *) SvRV(data),0,0 ));
+ lookup_data = *(av_fetch((AV *) SvRV(data),1,0 ));
- ENTER;
- SAVETMPS;
- PUSHMARK(SP);
+ ENTER;
+ SAVETMPS;
+ PUSHMARK(SP);
- XPUSHs(lookup_data);
- XPUSHs(sv_2mortal(C2Sv(name,NULL)));
- XPUSHs(sv_2mortal(C2Sv(ns_uri,NULL)));
- PUTBACK ;
+ XPUSHs(lookup_data);
+ XPUSHs(sv_2mortal(C2Sv(name,NULL)));
+ XPUSHs(sv_2mortal(C2Sv(ns_uri,NULL)));
+ PUTBACK ;
- count = perl_call_sv(lookup_func, G_SCALAR|G_EVAL);
+ count = perl_call_sv(lookup_func, G_SCALAR|G_EVAL);
- SPAGAIN;
- if (SvTRUE(ERRSV)) {
- POPs;
- croak("XPathContext: error coming back from variable lookup function. %s\n", SvPV(ERRSV, n_a));
- }
- if (count != 1) croak("XPathContext: variable lookup function returned more than one argument!\n");
+ SPAGAIN;
+ if (SvTRUE(ERRSV)) {
+ POPs;
+ croak("XPathContext: error coming back from variable lookup function. %s\n", SvPV(ERRSV, n_a));
+ }
+ if (count != 1) croak("XPathContext: variable lookup function returned more than one argument!\n");
- perl_result = POPs;
- if (!SvOK(perl_result)) {
- ret = (xmlXPathObjectPtr)xmlXPathNewCString("");
- goto FINISH;
- }
- /* convert perl result structures to LibXML structures */
- if (sv_isobject(perl_result) &&
- (SvTYPE(SvRV(perl_result)) == SVt_PVMG ||
- SvTYPE(SvRV(perl_result)) == SVt_PVAV))
- {
- if (sv_isa(perl_result, "XML::LibXML::NodeList")) {
- int i = 0;
- int len;
- /* warn("result is a node list\n"); */
- ret = (xmlXPathObjectPtr) xmlXPathNewNodeSet((xmlNodePtr) NULL);
- array_result = (AV*)SvRV(perl_result);
- len = av_len(array_result);
- for( i; i <= len ; i++ ) {
- tmp_node = (xmlNodePtr)PmmSvNode(*(av_fetch(array_result,i,0)));
- xmlXPathNodeSetAdd(ret->nodesetval, tmp_node);
- }
- goto FINISH;
- }
- else if (sv_isa(perl_result, "XML::LibXML::Node") ||
- sv_isa(perl_result, "XML::LibXML::Element") ||
- sv_isa(perl_result, "XML::LibXML::Attr") ||
- sv_isa(perl_result, "XML::LibXML::Text") ||
- sv_isa(perl_result, "XML::LibXML::Comment") ||
- sv_isa(perl_result, "XML::LibXML::Document") ||
- sv_isa(perl_result, "XML::LibXML::PI")) {
- /* warn("result is a node\n"); */
- ret = (xmlXPathObjectPtr)xmlXPathNewNodeSet(NULL);
- tmp_node = (xmlNodePtr)PmmSvNode(perl_result);
- xmlXPathNodeSetAdd(ret->nodesetval,tmp_node);
- goto FINISH;
- }
- else if (sv_isa(perl_result, "XML::LibXML::Boolean")) {
- /* warn("result is a boolean\n"); */
- tmp_int = SvIV(SvRV(perl_result));
- ret = (xmlXPathObjectPtr)xmlXPathNewBoolean(tmp_int);
- goto FINISH;
- }
- else if (sv_isa(perl_result, "XML::LibXML::Literal")) {
- /* warn("result is a literal\n"); */
- tmp_string = SvPV(SvRV(perl_result), n_a);
- ret = (xmlXPathObjectPtr)xmlXPathNewCString(tmp_string);
- goto FINISH;
- }
- else if (sv_isa(perl_result, "XML::LibXML::Number")) {
- /* warn("result is a number\n"); */
- tmp_double = SvNV(SvRV(perl_result));
- ret = (xmlXPathObjectPtr)xmlXPathNewFloat(tmp_double);
- goto FINISH;
- }
- } else if (SvNOK(perl_result) || SvIOK(perl_result)) {
- /* warn("result is an unblessed number\n"); */
- ret = (xmlXPathObjectPtr)xmlXPathNewFloat(SvNV(perl_result));
- } else {
- /* warn("result is an unblessed string\n"); */
- ret = (xmlXPathObjectPtr)xmlXPathNewCString(SvPV(perl_result, n_a));
- }
-
+ perl_result = POPs;
+ if (!SvOK(perl_result)) {
+ ret = (xmlXPathObjectPtr)xmlXPathNewCString("");
+ goto FINISH;
+ }
+ /* convert perl result structures to LibXML structures */
+ if (sv_isobject(perl_result) &&
+ (SvTYPE(SvRV(perl_result)) == SVt_PVMG ||
+ SvTYPE(SvRV(perl_result)) == SVt_PVAV))
+ {
+ if (sv_isa(perl_result, "XML::LibXML::NodeList")) {
+ int i = 0;
+ int len;
+ /* warn("result is a node list\n"); */
+ ret = (xmlXPathObjectPtr) xmlXPathNewNodeSet((xmlNodePtr) NULL);
+ array_result = (AV*)SvRV(perl_result);
+ len = av_len(array_result);
+ for( i; i <= len ; i++ ) {
+ tmp_node = (xmlNodePtr)PmmSvNode(*(av_fetch(array_result,i,0)));
+ xmlXPathNodeSetAdd(ret->nodesetval, tmp_node);
+ }
+ goto FINISH;
+ }
+ else if (sv_isa(perl_result, "XML::LibXML::Node") ||
+ sv_isa(perl_result, "XML::LibXML::Element") ||
+ sv_isa(perl_result, "XML::LibXML::Attr") ||
+ sv_isa(perl_result, "XML::LibXML::Text") ||
+ sv_isa(perl_result, "XML::LibXML::Comment") ||
+ sv_isa(perl_result, "XML::LibXML::Document") ||
+ sv_isa(perl_result, "XML::LibXML::PI")) {
+ /* warn("result is a node\n"); */
+ ret = (xmlXPathObjectPtr)xmlXPathNewNodeSet(NULL);
+ tmp_node = (xmlNodePtr)PmmSvNode(perl_result);
+ xmlXPathNodeSetAdd(ret->nodesetval,tmp_node);
+ goto FINISH;
+ }
+ else if (sv_isa(perl_result, "XML::LibXML::Boolean")) {
+ /* warn("result is a boolean\n"); */
+ tmp_int = SvIV(SvRV(perl_result));
+ ret = (xmlXPathObjectPtr)xmlXPathNewBoolean(tmp_int);
+ goto FINISH;
+ }
+ else if (sv_isa(perl_result, "XML::LibXML::Literal")) {
+ /* warn("result is a literal\n"); */
+ tmp_string = SvPV(SvRV(perl_result), n_a);
+ ret = (xmlXPathObjectPtr)xmlXPathNewCString(tmp_string);
+ goto FINISH;
+ }
+ else if (sv_isa(perl_result, "XML::LibXML::Number")) {
+ /* warn("result is a number\n"); */
+ tmp_double = SvNV(SvRV(perl_result));
+ ret = (xmlXPathObjectPtr)xmlXPathNewFloat(tmp_double);
+ goto FINISH;
+ }
+ } else if (SvNOK(perl_result) || SvIOK(perl_result)) {
+ /* warn("result is an unblessed number\n"); */
+ ret = (xmlXPathObjectPtr)xmlXPathNewFloat(SvNV(perl_result));
+ } else {
+ /* warn("result is an unblessed string\n"); */
+ ret = (xmlXPathObjectPtr)xmlXPathNewCString(SvPV(perl_result, n_a));
+ }
+
- FINISH:
+ FINISH:
- PUTBACK;
- FREETMPS;
- LEAVE;
- return ret;
+ PUTBACK;
+ FREETMPS;
+ LEAVE;
+ return ret;
}
/* ****************************************************************
@@ -188,212 +188,237 @@
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;
- SV * perl_result;
- ProxyNodePtr owner = NULL;
- char * tmp_string;
- STRLEN n_a;
- double tmp_double;
- int tmp_int;
- AV * array_result;
- xmlNodePtr tmp_node;
- SV *key;
- char *strkey;
- const char *function, *uri;
- SV **perl_function;
- int xslt_tree = 0;
- dSP;
- SV * data;
+ xmlXPathObjectPtr obj,ret;
+ xmlNodeSetPtr nodelist = NULL;
+ int count;
+ SV * perl_dispatch;
+ int i;
+ STRLEN len;
+ SV * perl_result;
+ ProxyNodePtr owner = NULL;
+ char * tmp_string;
+ STRLEN n_a;
+ double tmp_double;
+ int tmp_int;
+ AV * array_result;
+ xmlNodePtr tmp_node;
+ SV *key;
+ char *strkey;
+ const char *function, *uri;
+ SV **perl_function;
+ int xslt_tree = 0;
+ dSP;
+ SV * data;
- /* 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!\n");
- }
+ /* 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!\n");
+ }
- function = ctxt->context->function;
- uri = ctxt->context->functionURI;
+ function = ctxt->context->function;
+ uri = 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);
- SvREFCNT_dec(key);
+ 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);
+ SvREFCNT_dec(key);
- ENTER;
- SAVETMPS;
- PUSHMARK(SP);
+ ENTER;
+ SAVETMPS;
+ PUSHMARK(SP);
- XPUSHs(*perl_function);
+ XPUSHs(*perl_function);
- /* set up call to perl dispatcher function */
- for (i = 0; i < nargs; i++) {
- obj = (xmlXPathObjectPtr)valuePop(ctxt);
- xslt_tree = 0;
- switch (obj->type) {
- case XPATH_XSLT_TREE: /* PP: what's this? */
- warn("%d's argument to %s is XPATH_XSLT_TREE",i,function);
- xslt_tree = 1; /* PP: these are destroyed (they have boolval=1) */
- 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 = 0 ;
- const char * cls = "XML::LibXML::Node";
- xmlNodePtr tnode;
- SV * element;
+ /* set up call to perl dispatcher function */
+ for (i = 0; i < nargs; i++) {
+ obj = (xmlXPathObjectPtr)valuePop(ctxt);
+ xslt_tree = 0;
+ switch (obj->type) {
+ case XPATH_XSLT_TREE: /* PP: what's this? */
+ warn("%d's argument to %s is XPATH_XSLT_TREE",i,function);
+ xslt_tree = 1; /* PP: these are destroyed (they have boolval=1) */
+ 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 = 0 ;
+ const char * cls = "XML::LibXML::Node";
+ xmlNodePtr tnode;
+ SV * element;
- len = nodelist->nodeNr;
- for( j ; j < len; j++){
- tnode = nodelist->nodeTab[j];
- if( tnode != NULL && tnode->doc != NULL) {
- owner = SvPROXYNODE(sv_2mortal(PmmNodeToSv((xmlNodePtr)(tnode->doc), NULL)));
- }
- if (tnode->type == XML_NAMESPACE_DECL) {
- element = sv_newmortal();
- cls = PmmNodeTypeName( tnode );
- element = sv_setref_pv( element,
- (const char *)cls,
- (void *)xmlCopyNamespace((xmlNsPtr)tnode)
- );
- }
- else {
- /* need to copy the node as libxml2 will free it */
- /* PP: I guess its only true for XSLT_TREEs */
- if (xslt_tree) {
- xmlNodePtr tnode_cpy = xmlCopyNode(tnode, 1);
- element = PmmNodeToSv(tnode_cpy, owner);
- } 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)));
- }
- 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((char*)xmlXPathCastToString(obj), 0)));
- }
- xmlXPathFreeObject(obj);
- }
+ len = nodelist->nodeNr;
+ for( j ; j < len; j++){
+ tnode = nodelist->nodeTab[j];
+ if( tnode != NULL && tnode->doc != NULL) {
+ owner = SvPROXYNODE(sv_2mortal(PmmNodeToSv((xmlNodePtr)(tnode->doc), NULL)));
+ }
+ if (tnode->type == XML_NAMESPACE_DECL) {
+ element = sv_newmortal();
+ cls = PmmNodeTypeName( tnode );
+ element = sv_setref_pv( element,
+ (const char *)cls,
+ (void *)xmlCopyNamespace((xmlNsPtr)tnode)
+ );
+ }
+ else {
+ /* need to copy the node as libxml2 will free it */
+ /* PP: I guess its only true for XSLT_TREEs */
+ if (xslt_tree) {
+ xmlNodePtr tnode_cpy = xmlCopyNode(tnode, 1);
+ element = PmmNodeToSv(tnode_cpy, owner);
+ } 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)));
+ }
+ 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((char*)xmlXPathCastToString(obj), 0)));
+ }
+ xmlXPathFreeObject(obj);
+ }
- /* call perl dispatcher */
- PUTBACK;
+ /* call perl dispatcher */
+ PUTBACK;
- perl_dispatch = sv_2mortal(newSVpv("XML::LibXML::XPathContext::perl_dispatcher",0));
- count = perl_call_sv(perl_dispatch, G_SCALAR|G_EVAL);
+ perl_dispatch = sv_2mortal(newSVpv("XML::LibXML::XPathContext::perl_dispatcher",0));
+ count = perl_call_sv(perl_dispatch, G_SCALAR|G_EVAL);
- SPAGAIN;
+ SPAGAIN;
- if (SvTRUE(ERRSV)) {
- POPs;
- croak("XPathContext: error coming back from perl-dispatcher in pm file. %s\n", SvPV(ERRSV, n_a));
- }
+ if (SvTRUE(ERRSV)) {
+ POPs;
+ croak("XPathContext: error coming back from perl-dispatcher in pm file. %s\n", SvPV(ERRSV, n_a));
+ }
- if (count != 1) croak("XPathContext: perl-dispatcher in pm file returned more than one argument!\n");
+ if (count != 1) croak("XPathContext: perl-dispatcher in pm file returned more than one argument!\n");
- perl_result = POPs;
- if (!SvOK(perl_result)) {
- ret = (xmlXPathObjectPtr)xmlXPathNewCString("");
- goto FINISH;
- }
+ perl_result = POPs;
+ if (!SvOK(perl_result)) {
+ ret = (xmlXPathObjectPtr)xmlXPathNewCString("");
+ goto FINISH;
+ }
- /* convert perl result structures to LibXML structures */
- if (sv_isobject(perl_result) &&
- (SvTYPE(SvRV(perl_result)) == SVt_PVMG ||
- SvTYPE(SvRV(perl_result)) == SVt_PVAV))
- {
- if (sv_isa(perl_result, "XML::LibXML::NodeList")) {
- i = 0;
- /* warn("result is a node list\n"); */
- ret = (xmlXPathObjectPtr)xmlXPathNewNodeSet(NULL);
- array_result = (AV*)SvRV(perl_result);
- len = av_len(array_result);
- for( i; i <= len ; i++ ) {
- tmp_node = (xmlNodePtr)PmmSvNode(*(av_fetch(array_result,i,0)));
- xmlXPathNodeSetAdd(ret->nodesetval, tmp_node);
- }
- goto FINISH;
- }
- else if (sv_isa(perl_result, "XML::LibXML::Node") ||
- sv_isa(perl_result, "XML::LibXML::Element") ||
- sv_isa(perl_result, "XML::LibXML::Attr") ||
- sv_isa(perl_result, "XML::LibXML::Text") ||
- sv_isa(perl_result, "XML::LibXML::Comment") ||
- sv_isa(perl_result, "XML::LibXML::Document") ||
- sv_isa(perl_result, "XML::LibXML::PI")) {
- /* warn("result is a node\n"); */
- ret = (xmlXPathObjectPtr)xmlXPathNewNodeSet(NULL);
- tmp_node = (xmlNodePtr)PmmSvNode(perl_result);
- xmlXPathNodeSetAdd(ret->nodesetval,tmp_node);
- goto FINISH;
- }
- else if (sv_isa(perl_result, "XML::LibXML::Boolean")) {
- /* warn("result is a boolean\n"); */
- tmp_int = SvIV(SvRV(perl_result));
- ret = (xmlXPathObjectPtr)xmlXPathNewBoolean(tmp_int);
- goto FINISH;
- }
- else if (sv_isa(perl_result, "XML::LibXML::Literal")) {
- /* warn("result is a literal\n"); */
- tmp_string = SvPV(SvRV(perl_result), len);
- ret = (xmlXPathObjectPtr)xmlXPathNewCString(tmp_string);
- goto FINISH;
- }
- else if (sv_isa(perl_result, "XML::LibXML::Number")) {
- /* warn("result is a number\n"); */
- tmp_double = SvNV(SvRV(perl_result));
- ret = (xmlXPathObjectPtr)xmlXPathNewFloat(tmp_double);
- goto FINISH;
- }
- } else if (SvNOK(perl_result) || SvIOK(perl_result)) {
- /* warn("result is an unblessed number\n"); */
- ret = (xmlXPathObjectPtr)xmlXPathNewFloat(SvNV(perl_result));
- } else {
- /* warn("result is an unblessed string\n"); */
- ret = (xmlXPathObjectPtr)xmlXPathNewCString(SvPV(perl_result, n_a));
- }
+ /* convert perl result structures to LibXML structures */
+ if (sv_isobject(perl_result) &&
+ (SvTYPE(SvRV(perl_result)) == SVt_PVMG ||
+ SvTYPE(SvRV(perl_result)) == SVt_PVAV))
+ {
+ if (sv_isa(perl_result, "XML::LibXML::NodeList")) {
+ i = 0;
+ /* warn("result is a node list\n"); */
+ ret = (xmlXPathObjectPtr)xmlXPathNewNodeSet(NULL);
+ array_result = (AV*)SvRV(perl_result);
+ len = av_len(array_result);
+ for( i; i <= len ; i++ ) {
+ tmp_node = (xmlNodePtr)PmmSvNode(*(av_fetch(array_result,i,0)));
+ xmlXPathNodeSetAdd(ret->nodesetval, tmp_node);
+ }
+ goto FINISH;
+ }
+ else if (sv_isa(perl_result, "XML::LibXML::Node") ||
+ sv_isa(perl_result, "XML::LibXML::Element") ||
+ sv_isa(perl_result, "XML::LibXML::Attr") ||
+ sv_isa(perl_result, "XML::LibXML::Text") ||
+ sv_isa(perl_result, "XML::LibXML::Comment") ||
+ sv_isa(perl_result, "XML::LibXML::Document") ||
+ sv_isa(perl_result, "XML::LibXML::PI")) {
+ /* warn("result is a node\n"); */
+ ret = (xmlXPathObjectPtr)xmlXPathNewNodeSet(NULL);
+ tmp_node = (xmlNodePtr)PmmSvNode(perl_result);
+ warn("NODE: perl mortality count %d\n",
+ SvREFCNT(SvRV(perl_result)));
+ warn("NODE: owner mortality count %d\n",
+ PmmREFCNT(PmmOWNERPO(((ProxyNodePtr)(tmp_node->_private)))));
+ warn("NODE: mortality count %d\n",
+ PmmREFCNT(((ProxyNodePtr)(tmp_node->_private))));
+ warn("NODE: is proxy %d\n",
+ (((ProxyNodePtr)(tmp_node->_private))->node == tmp_node));
- FINISH:
+ /* safely remove the node from perl structures without */
+ /* deleting any real libxml2 object */
+ if (SvREFCNT(SvRV(perl_result))==1) {
+ int result=PmmREFCNT_dec_flag_delete(SvPROXYNODE(perl_result));
+ warn("NODE PmmREFCNT_dec_flag_delete: %d\n",result);
+ sv_setiv(SvRV(perl_result),0); /* make DESTROY do nothing */
+ }
+ /* now, this is a memory leak; something has to be done */
+ /* with the nodes for which PmmREFCNT_dec_flag_delete */
+ /* returned 0 */
- valuePush(ctxt, ret);
- PUTBACK;
- FREETMPS;
- LEAVE;
+ xmlXPathNodeSetAdd(ret->nodesetval,tmp_node);
+ warn("NODE: goto finish\n");
+ goto FINISH;
+ }
+ else if (sv_isa(perl_result, "XML::LibXML::Boolean")) {
+ /* warn("result is a boolean\n"); */
+ tmp_int = SvIV(SvRV(perl_result));
+ ret = (xmlXPathObjectPtr)xmlXPathNewBoolean(tmp_int);
+ goto FINISH;
+ }
+ else if (sv_isa(perl_result, "XML::LibXML::Literal")) {
+ /* warn("result is a literal\n"); */
+ tmp_string = SvPV(SvRV(perl_result), len);
+ ret = (xmlXPathObjectPtr)xmlXPathNewCString(tmp_string);
+ goto FINISH;
+ }
+ else if (sv_isa(perl_result, "XML::LibXML::Number")) {
+ /* warn("result is a number\n"); */
+ tmp_double = SvNV(SvRV(perl_result));
+ ret = (xmlXPathObjectPtr)xmlXPathNewFloat(tmp_double);
+ goto FINISH;
+ }
+ } else if (SvNOK(perl_result) || SvIOK(perl_result)) {
+ /* warn("result is an unblessed number\n"); */
+ ret = (xmlXPathObjectPtr)xmlXPathNewFloat(SvNV(perl_result));
+ } else {
+ /* warn("result is an unblessed string\n"); */
+ ret = (xmlXPathObjectPtr)xmlXPathNewCString(SvPV(perl_result, n_a));
+ }
+
+ FINISH:
+ fprintf(stderr,"NODE: value push\n");
+ valuePush(ctxt, ret);
+ fprintf(stderr,"NODE: putback\n");
+ PUTBACK;
+ fprintf(stderr,"NODE: freetmps\n");
+ FREETMPS;
+ fprintf(stderr,"NODE: leave\n");
+ LEAVE;
+ fprintf(stderr,"NODE: left\n");
}
MODULE = XML::LibXML::XPathContext PACKAGE = XML::LibXML::XPathContext
@@ -409,6 +434,10 @@
ctxt = xmlXPathNewContext( node->doc );
ctxt->node = node;
+ /* we want the node and doc live as long as ctxt does */
+ PmmREFCNT_inc(SvPROXYNODE(pnode));
+ PmmREFCNT_inc(PmmNewNode((xmlNodePtr)node->doc));
+
/* get the namespace information */
if (node->type == XML_DOCUMENT_NODE) {
ctxt->namespaces = xmlGetNsList( node->doc,
@@ -441,19 +470,89 @@
CODE:
xs_warn( "DESTROY XPATH CONTEXT" );
if (ctxt) {
- if (ctxt->namespaces != NULL) {
- xmlFree( ctxt->namespaces );
- }
- if (ctxt->varLookupData != NULL && SvROK((SV*)ctxt->varLookupData)
- && SvTYPE(SvRV((SV *)ctxt->varLookupData)) == SVt_PVAV) {
- SvREFCNT_dec((SV *)ctxt->varLookupData);
- }
- if (ctxt->funcLookupData != NULL && SvROK((SV*)ctxt->funcLookupData)
- && SvTYPE(SvRV((SV *)ctxt->funcLookupData)) == SVt_PVHV) {
- SvREFCNT_dec((SV *)ctxt->funcLookupData);
- }
-
- xmlXPathFreeContext(ctxt);
+ if (ctxt->node) {
+ PmmREFCNT_dec(ctxt->node->_private);
+ }
+ if (ctxt->doc) {
+ PmmREFCNT_dec(ctxt->doc->_private);
+ }
+
+ if (ctxt->namespaces != NULL) {
+ xmlFree( ctxt->namespaces );
+ }
+ if (ctxt->varLookupData != NULL && SvROK((SV*)ctxt->varLookupData)
+ && SvTYPE(SvRV((SV *)ctxt->varLookupData)) == SVt_PVAV) {
+ SvREFCNT_dec((SV *)ctxt->varLookupData);
+ }
+ 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 = (xmlXPathContextPtr)SvIV(SvRV(self));
+ CODE:
+ if (ctxt->node != NULL) {
+ RETVAL = PmmNodeToSv(ctxt->node,
+ PmmOWNERPO( PmmPROXYNODE(ctxt->node)));
+
+ } else {
+ warn("XPathContext: lost context node\n");
+ RETVAL = &PL_sv_undef;
+ }
+OUTPUT:
+ RETVAL
+
+void
+setContextNode( self , pnode )
+ SV * self
+ SV * pnode
+ INIT:
+ xmlNodePtr node = PmmSvNode(pnode);
+ xmlXPathContextPtr ctxt = (xmlXPathContextPtr)SvIV(SvRV(self));
+ PPCODE:
+ if (node != NULL) {
+ /* we want the node and doc live as long as ctxt does */
+ PmmREFCNT_inc(SvPROXYNODE(pnode));
+ PmmREFCNT_inc(PmmNewNode((xmlNodePtr)node->doc));
+
+ if (ctxt->node != NULL) {
+ PmmREFCNT_dec(ctxt->node->_private);
+ } else {
+ warn("XPathContext: Lost previous context node");
+ }
+ if (ctxt->doc != NULL) {
+ PmmREFCNT_dec(ctxt->doc->_private);
+ } else {
+ warn("XPathContext: Lost previous document node");
+ }
+ ctxt->node = node;
+ ctxt->doc = node->doc;
+
+ /* free old namespace information */
+ if (ctxt->namespaces != NULL) {
+ xmlFree( ctxt->namespaces );
+ }
+ /* get new namespace information */
+ 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) {
+ while (ctxt->namespaces[ctxt->nsNr] != NULL)
+ ctxt->nsNr++;
+ }
+ } else {
+ croak("XPathContext: Cannot set an undefined context node");
}
void
@@ -482,13 +581,13 @@
xmlXPathContextPtr ctxt = (xmlXPathContextPtr)SvIV(SvRV(self));
CODE:
if (ctxt->varLookupData != NULL &&
- SvROK((SV*)(ctxt->varLookupData)) &&
- SvTYPE(SvRV((SV*)(ctxt->varLookupData))) == SVt_PVAV) {
- RETVAL = *(av_fetch((AV *) SvRV((SV*)(ctxt->varLookupData)),1,0));
- SvREFCNT_inc(RETVAL);
+ SvROK((SV*)(ctxt->varLookupData)) &&
+ SvTYPE(SvRV((SV*)(ctxt->varLookupData))) == SVt_PVAV) {
+ RETVAL = *(av_fetch((AV *) SvRV((SV*)(ctxt->varLookupData)),1,0));
+ SvREFCNT_inc(RETVAL);
} else {
- RETVAL = &PL_sv_undef;
- }
+ RETVAL = &PL_sv_undef;
+ }
OUTPUT:
RETVAL
@@ -509,26 +608,26 @@
croak( "missing xpath context" );
}
if ( SvROK(lookup_func) && SvTYPE(SvRV(lookup_func)) == SVt_PVCV ) {
- pfdr = newRV_inc((SV*) newAV());
- av_push((AV *)SvRV(pfdr), SvREFCNT_inc(lookup_func));
- av_push((AV *)SvRV(pfdr), SvREFCNT_inc(lookup_data));
+ pfdr = newRV_inc((SV*) newAV());
+ av_push((AV *)SvRV(pfdr), SvREFCNT_inc(lookup_func));
+ av_push((AV *)SvRV(pfdr), SvREFCNT_inc(lookup_data));
} else {
croak( "1st argument is not a CODE reference" );
}
if (ctxt->varLookupData != NULL) {
- if (SvTYPE(SvRV((SV *)ctxt->varLookupData)) == SVt_PVAV) {
- SvREFCNT_dec((SV *)ctxt->varLookupData);
- ctxt->varLookupData = NULL;
- ctxt->varLookupFunc = NULL;
- } else {
- croak("can't register: varLookupData slot already occupied\n");
- }
- }
+ if (SvTYPE(SvRV((SV *)ctxt->varLookupData)) == SVt_PVAV) {
+ SvREFCNT_dec((SV *)ctxt->varLookupData);
+ ctxt->varLookupData = NULL;
+ ctxt->varLookupFunc = NULL;
+ } else {
+ croak("can't register: varLookupData slot already occupied\n");
+ }
+ }
PPCODE:
xmlXPathRegisterVariableLookup(ctxt, LibXML_generic_variable_lookup, pfdr);
if (ctxt->varLookupData==NULL || ctxt->varLookupData != pfdr) {
- croak( "registrating failed\n" );
- }
+ croak( "registrating failed\n" );
+ }
void
registerFunctionNS( pxpath_context, name, uri, func)
@@ -549,39 +648,39 @@
croak( "missing xpath context" );
}
if ( SvTYPE(SvRV(func)) == SVt_PVCV ) {
- if (ctxt->funcLookupData == NULL) {
- pfdr = newRV_inc((SV*) newHV());
- ctxt->funcLookupData = pfdr;
- } else {
- if (SvTYPE(SvRV((SV *)ctxt->funcLookupData)) == SVt_PVHV) {
- /* good, it's a HV */
- pfdr = (SV *)ctxt->funcLookupData;
- } else {
- croak ( "can't 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); */
- hv_store((HV *)SvRV(pfdr),strkey, len, SvREFCNT_inc(func), 0);
- SvREFCNT_dec(key);
- } else {
- croak( "function is not a CODE reference\n" );
+ if (ctxt->funcLookupData == NULL) {
+ pfdr = newRV_inc((SV*) newHV());
+ ctxt->funcLookupData = pfdr;
+ } else {
+ if (SvTYPE(SvRV((SV *)ctxt->funcLookupData)) == SVt_PVHV) {
+ /* good, it's a HV */
+ pfdr = (SV *)ctxt->funcLookupData;
+ } else {
+ croak ( "can't 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); */
+ hv_store((HV *)SvRV(pfdr),strkey, len, SvREFCNT_inc(func), 0);
+ SvREFCNT_dec(key);
+ } else {
+ croak( "function is not a CODE reference\n" );
}
PPCODE:
if (SvOK(uri)) {
- /* warn("Registering function with NS '%s' (uri: %s)\n", name, uri); */
- xmlXPathRegisterFuncNS(ctxt, name, SvPV(uri, len), LibXML_generic_extension_function);
- } else {
- /* warn("Registering function '%s'\n", name); */
- xmlXPathRegisterFunc(ctxt, name, LibXML_generic_extension_function);
- }
+ /* warn("Registering function with NS '%s' (uri: %s)\n", name, uri); */
+ xmlXPathRegisterFuncNS(ctxt, name, SvPV(uri, len), LibXML_generic_extension_function);
+ } else {
+ /* warn("Registering function '%s'\n", name); */
+ xmlXPathRegisterFunc(ctxt, name, LibXML_generic_extension_function);
+ }
void
_findnodes( pxpath_context, perl_xpath )
Index: XPathContext.pm
===================================================================
RCS file: /cvsroot/perl-xml/XML-LibXML-XPathContext/XPathContext.pm,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- XPathContext.pm 14 Mar 2003 16:37:45 -0000 1.4
+++ XPathContext.pm 16 Mar 2003 16:21:29 -0000 1.5
@@ -189,6 +189,14 @@
certain shortcuts. This could be used as the equivalent of
<xsl:value-of select="some_xpath"/>.
+=item B<getContextNode()>
+
+Get current context node.
+
+=item B<setContextNode($node)>
+
+Set current context node.
+
=back
=head1 AUTHORS
|