|
View:
New views
1 Messages
—
Rating Filter:
Alert me
|
|
|
Fix for XPath with default namespaceThis fixes the issues mentioned before.
If your document uses a default namespace, that is, a namespace without a prefix, then you should register a default namespace with gdome_xpnsresolv_registerNs() and use this prefix with XPaths. Tested with gdome-test-xpath-ns.c and did run against valgrind without leaks. -- Gustavo Sverzut Barbieri ------------------------ Instituto Nokia de Tecnologia - INdT Jabber: barbieri@... MSN: barbieri@... ICQ#: 17249123 Skype: gsbarbieri Mobile: +55 (81) 9927 0010 Phone: +1 (347) 624 6296; 08122692@... GPG: 0xB640E1A2 @ wwwkeys.pgp.net [gdome2-cvs-xpath.patch] diff -x '*.a' -x '*.so' -x '*.o' -x CVS -x Makefile -ur gdome2/libgdome/gdome-xpath.c gdome2-fix/libgdome/gdome-xpath.c --- gdome2/libgdome/gdome-xpath.c 2002-03-01 01:00:20.000000000 -0300 +++ gdome2-fix/libgdome/gdome-xpath.c 2006-03-31 17:22:36.000000000 -0300 @@ -204,6 +204,28 @@ *exc = 0; return ((Gdome_xpath_XPathNSResolver *)self)->vtab->lookupNamespaceURI (self, prefix, exc); } +/** + * gdome_xpnsresolv_registerNs: + * @self: GdomeXPathNSResolver Object ref + * @prefix: The prefix of the namespace to look for + * @uri: The URI to associate to the given namespace + * @exc: Exception Object ref + * + * Associate prefix with URI to use with this namespace resolver. + */ +void +gdome_xpnsresolv_registerNs (GdomeXPathNSResolver *self, GdomeDOMString *prefix, GdomeDOMString *uri, GdomeException *exc) +{ + g_assert (exc != NULL); + + if (self == NULL) + *exc = GDOME_NULL_POINTER_ERR; + else + *exc = GDOME_NOEXCEPTION_ERR; + + ((Gdome_xpath_XPathNSResolver *)self)->vtab->registerNs (self, prefix, uri, exc); +} + /****************************************************************************** GdomeXPathResult interface API diff -x '*.a' -x '*.so' -x '*.o' -x CVS -x Makefile -ur gdome2/libgdome/gdome-xpath.h gdome2-fix/libgdome/gdome-xpath.h --- gdome2/libgdome/gdome-xpath.h 2002-03-01 01:00:20.000000000 -0300 +++ gdome2-fix/libgdome/gdome-xpath.h 2006-03-30 21:31:28.000000000 -0300 @@ -69,10 +69,13 @@ GdomeXPathNSResolver * gdome_xpeval_createNSResolver (GdomeXPathEvaluator *self, GdomeNode *nodeResolver, GdomeException *exc); GdomeXPathResult * gdome_xpeval_createResult (GdomeXPathEvaluator *self, GdomeException *exc); GdomeXPathResult *gdome_xpeval_evaluate (GdomeXPathEvaluator *self, GdomeDOMString *expression, GdomeNode *contextNode, GdomeXPathNSResolver *resolver, unsigned int type, GdomeXPathResult *result, GdomeException *exc); + GdomeXPathNSResolver * gdome_xpnsresolv_mkref( GdomeNode *nodeResolver ); void gdome_xpnsresolv_ref (GdomeXPathNSResolver *self, GdomeException *exc); void gdome_xpnsresolv_unref (GdomeXPathNSResolver *self, GdomeException *exc); GdomeDOMString * gdome_xpnsresolv_lookupNamespaceURI( GdomeXPathNSResolver *self, GdomeDOMString *prefix, GdomeException *exc); +void gdome_xpnsresolv_registerNs (GdomeXPathNSResolver *self, GdomeDOMString *prefix, GdomeDOMString *uri, GdomeException *exc); + void gdome_xpresult_ref (GdomeXPathResult *self, GdomeException *exc); void gdome_xpresult_unref (GdomeXPathResult *self, GdomeException *exc); unsigned short gdome_xpresult_resultType (GdomeXPathResult *self, GdomeException *exc); diff -x '*.a' -x '*.so' -x '*.o' -x CVS -x Makefile -ur gdome2/libgdome/xpath/gdome-xpath-xpeval.c gdome2-fix/libgdome/xpath/gdome-xpath-xpeval.c --- gdome2/libgdome/xpath/gdome-xpath-xpeval.c 2002-03-01 00:33:26.000000000 -0300 +++ gdome2-fix/libgdome/xpath/gdome-xpath-xpeval.c 2006-03-31 17:09:23.000000000 -0300 @@ -163,6 +163,7 @@ xmlNodePtr refNode; xmlChar *path; Gdome_xml_Node *cn = (Gdome_xml_Node *)contextNode; + int free_namespaces = 1; Gdome_xpath_XPathNSResolver *resolv = (Gdome_xpath_XPathNSResolver *)resolver; g_return_val_if_fail (expression != NULL, NULL); @@ -178,13 +179,29 @@ while (ctxt->namespaces[ctxt->nsNr] != NULL) ctxt->nsNr++; } + if (resolv->nslist != NULL) { + if (ctxt->namespaces != NULL) { + int i = ctxt->nsNr; + ctxt->nsNr += resolv->nslist_size; + ctxt->namespaces = (xmlNsPtr *) xmlRealloc (ctxt->namespaces, + (ctxt->nsNr + 1) * + sizeof (xmlNsPtr)); + memcpy (ctxt->namespaces + i, resolv->nslist, + resolv->nslist_size * sizeof (xmlNsPtr)); + ctxt->namespaces[ctxt->nsNr] = NULL; + } else { + ctxt->namespaces = resolv->nslist; + free_namespaces = 0; + ctxt->nsNr = resolv->nslist_size; + } + } } path = expression->str; res = xmlXPathEval( path, ctxt ); /* XML::LibXML should also have this patch... */ - if (ctxt->namespaces != NULL) + if ((ctxt->namespaces != NULL) && free_namespaces) xmlFree(ctxt->namespaces); xmlXPathFreeContext(ctxt); diff -x '*.a' -x '*.so' -x '*.o' -x CVS -x Makefile -ur gdome2/libgdome/xpath/gdome-xpath-xpnsresolv.c gdome2-fix/libgdome/xpath/gdome-xpath-xpnsresolv.c --- gdome2/libgdome/xpath/gdome-xpath-xpnsresolv.c 2002-03-01 00:33:46.000000000 -0300 +++ gdome2-fix/libgdome/xpath/gdome-xpath-xpnsresolv.c 2006-03-31 17:23:19.000000000 -0300 @@ -34,7 +34,8 @@ { gdome_xpath_xpnsresolv_ref, gdome_xpath_xpnsresolv_unref, - gdome_xpath_xpnsresolv_lookupNamespaceURI + gdome_xpath_xpnsresolv_lookupNamespaceURI, + gdome_xpath_xpnsresolv_registerNs }; GdomeXPathNSResolver * @@ -48,6 +49,8 @@ resolv->n = priv->n; resolv->refcnt = 1; resolv->gnode = nodeResolver; + resolv->nslist = NULL; + resolv->nslist_size = 0; gdome_xml_n_ref ( nodeResolver, &exc); return (GdomeXPathNSResolver *)resolv; } @@ -90,6 +93,17 @@ priv->refcnt--; if (priv->refcnt == 0) { + if (priv->nslist) { + unsigned i; + xmlNsPtr ns = *priv->nslist; + for (i=0; i < priv->nslist_size; i++, ns++) { + xmlFree ((char*)ns->href); + xmlFree ((char*)ns->prefix); + xmlFree (ns); + } + + xmlFree (priv->nslist); + } gdome_xml_n_unref (priv->gnode, exc); g_free (self); } @@ -119,3 +133,41 @@ return NULL; } } + +/** + * gdome_xpath_xpnsresolv_registerNs: + * @self: GdomeXPathNSResolver Object ref + * @prefix: The prefix of the namespace to look for + * @uri: The URI to associate to the given namespace + * @exc: Exception Object ref + * + * Associate prefix with URI to use with this namespace resolver. + */ +void +gdome_xpath_xpnsresolv_registerNs (GdomeXPathNSResolver *self, GdomeDOMString *prefix, GdomeDOMString *uri, GdomeException *exc) +{ + Gdome_xpath_XPathNSResolver *priv = (Gdome_xpath_XPathNSResolver *)self; + xmlNsPtr ns; + + g_assert( exc != NULL ); + + if ((self == NULL) || (prefix == NULL) || (uri == NULL)) + *exc = GDOME_NULL_POINTER_ERR; + + if (priv->nslist == NULL) { + priv->nslist_size = 1; + priv->nslist = (xmlNsPtr *) xmlMalloc (2 * sizeof (xmlNsPtr)); + } else { + priv->nslist_size ++; + priv->nslist = (xmlNsPtr *) xmlRealloc (priv->nslist, + (priv->nslist_size + 1) * + sizeof (xmlNsPtr)); + } + ns = (xmlNsPtr) xmlMalloc (sizeof (xmlNs)); + memset (ns, 0, sizeof(xmlNs)); + ns->href = xmlStrdup (uri->str); + ns->prefix = xmlStrdup (prefix->str); + + priv->nslist[priv->nslist_size - 1] = ns; + priv->nslist[priv->nslist_size] = NULL; +} diff -x '*.a' -x '*.so' -x '*.o' -x CVS -x Makefile -ur gdome2/libgdome/xpath/gdome-xpath-xpnsresolv.h gdome2-fix/libgdome/xpath/gdome-xpath-xpnsresolv.h --- gdome2/libgdome/xpath/gdome-xpath-xpnsresolv.h 2005-12-03 06:29:18.000000000 -0300 +++ gdome2-fix/libgdome/xpath/gdome-xpath-xpnsresolv.h 2006-03-30 21:14:33.000000000 -0300 @@ -25,6 +25,7 @@ void (*ref) (GdomeXPathNSResolver *self, GdomeException *exc); void (*unref) (GdomeXPathNSResolver *self, GdomeException *exc); GdomeDOMString *(*lookupNamespaceURI) (GdomeXPathNSResolver *self, GdomeDOMString *prefix, GdomeException *exc); + void (*registerNs) (GdomeXPathNSResolver *self, GdomeDOMString *prefix, GdomeDOMString *uri, GdomeException *exc); }; typedef struct _Gdome_xpath_XPathNSResolver Gdome_xpath_XPathNSResolver; @@ -35,12 +36,15 @@ GdomeNode *gnode; xmlNodePtr n; + xmlNsPtr *nslist; + unsigned nslist_size; }; GdomeXPathNSResolver * gdome_xpath_xpnsresolv_mkref( GdomeNode *nodeResolver ); void gdome_xpath_xpnsresolv_ref (GdomeXPathNSResolver *self, GdomeException *exc); void gdome_xpath_xpnsresolv_unref (GdomeXPathNSResolver *self, GdomeException *exc); GdomeDOMString * gdome_xpath_xpnsresolv_lookupNamespaceURI( GdomeXPathNSResolver *self, GdomeDOMString *prefix, GdomeException *exc); +void gdome_xpath_xpnsresolv_registerNs (GdomeXPathNSResolver *self, GdomeDOMString *prefix, GdomeDOMString *uri, GdomeException *exc); extern const GdomeXPathNSResolverVtab gdome_xpath_xpnsresolv_vtab; [gdome-test-xpath-ns.c] #include <gdome.h> #include <gdome-xpath.h> #include <stdio.h> #include <string.h> static char uri[] = "http://www.indt.org.br"; static char xml[] = \ "<doc xmlns=\"http://www.indt.org.br\">" \ "<a><b><p attr=\"name1\">value1.1</p><p attr=\"name2\">value1.2</p></b></a>" \ "<d><p attr=\"name1\">value2</p></d>" \ "</doc>"; GdomeXPathResult * xpath_node( const char *expr, const char *prefix, const char *uri, GdomeNode *context, GdomeException *exc ) { GdomeException clean_exc = GDOME_NOEXCEPTION_ERR; GdomeXPathResult *res = NULL; GdomeXPathEvaluator *eval = NULL; GdomeDOMString *s = NULL, *s_prefix = NULL, *s_uri = NULL; GdomeDocument *doc = NULL; GdomeElement *root = NULL; GdomeXPathNSResolver *nsresolv = NULL; if ( gdome_n_nodeType( context, exc ) == GDOME_DOCUMENT_NODE ) { doc = (GdomeDocument*)context; gdome_doc_ref( doc, exc ); } else doc = gdome_n_ownerDocument( context, exc ); if ( *exc ) goto clean_up; root = gdome_doc_documentElement( doc, exc ); if ( *exc ) goto clean_up; eval = gdome_xpeval_mkref(); g_assert( eval ); nsresolv = gdome_xpeval_createNSResolver( eval, (GdomeNode*)root, exc ); if ( *exc ) goto clean_up; s_prefix = gdome_str_mkref( prefix ); s_uri = gdome_str_mkref( uri ); gdome_xpnsresolv_registerNs( nsresolv, s_prefix, s_uri, exc ); if ( *exc ) goto clean_up; s = gdome_str_mkref( expr ); g_assert( s ); res = gdome_xpeval_evaluate( eval, s, context, nsresolv, 0, NULL, exc ); if ( *exc ) goto clean_up; clean_up: if ( s ) gdome_str_unref( s ); if ( s_prefix ) gdome_str_unref( s_prefix ); if ( s_uri ) gdome_str_unref( s_uri ); if ( eval ) gdome_xpeval_unref( eval, &clean_exc ); if ( nsresolv ) gdome_xpnsresolv_unref( nsresolv, &clean_exc ); if ( root ) gdome_el_unref( root, &clean_exc ); if ( doc ) gdome_doc_unref( doc, &clean_exc ); return res; } GdomeXPathResult * xpath_xml( const char *expr, const char *prefix, const char *uri, char *xml, GdomeDocument *doc, GdomeException *exc ) { GdomeException clean_exc = GDOME_NOEXCEPTION_ERR; GdomeDOMImplementation *domimpl = NULL; GdomeXPathResult *res = NULL; domimpl = gdome_di_mkref(); doc = gdome_di_createDocFromMemory( domimpl, xml, GDOME_LOAD_PARSING, exc ); if ( *exc ) goto clean_up; res = xpath_node( expr, prefix, uri, (GdomeNode*)doc, exc ); if ( *exc ) goto clean_up; clean_up: if ( domimpl ) gdome_di_unref( domimpl, &clean_exc ); return res; } int test_root( void ) { GdomeException exc = GDOME_NOEXCEPTION_ERR; GdomeDocument *doc = NULL; GdomeXPathResult *res = xpath_xml( "/", "ns", uri, xml, doc, &exc ); GdomeNode *n = NULL; GdomeDOMString *s = NULL; unsigned i = 0; g_assert( res ); while ( ( n = gdome_xpresult_iterateNext( res, &exc ) ) != NULL ) { s = gdome_n_nodeName( n, &exc ); if ( exc ) goto clean_up; g_assert( strcmp( "#document", s->str ) == 0 ); gdome_str_unref( s ); s = NULL; gdome_n_unref( n, &exc ); if ( exc ) goto clean_up; n = NULL; i++; } g_assert( i == 1 ); clean_up: if ( exc ) fprintf( stderr, "Exception: %d\n", exc ); if ( s ) gdome_str_unref( s ); if ( n ) gdome_n_unref( n, &exc ); if ( res ) gdome_xpresult_unref( res, &exc ); if ( doc ) gdome_doc_unref( doc, &exc ); return exc; } int test_complete( void ) { GdomeException exc = GDOME_NOEXCEPTION_ERR; GdomeDocument *doc = NULL; GdomeXPathResult *res = xpath_xml( "//ns:a/ns:b/ns:p[@attr='name1']/text()", "ns", uri, xml, doc, &exc ); GdomeNode *n = NULL; GdomeDOMString *s = NULL; unsigned i = 0; g_assert( res ); while ( ( n = gdome_xpresult_iterateNext( res, &exc ) ) != NULL ) { s = gdome_t_data( (GdomeText*)n, &exc ); if ( exc ) goto clean_up; g_assert( strcmp( s->str, "value1.1" ) == 0 ); gdome_str_unref( s ); s = NULL; gdome_n_unref( n, &exc ); if ( exc ) goto clean_up; n = NULL; i++; } g_assert( i == 1 ); clean_up: if ( exc ) fprintf( stderr, "Exception: %d\n", exc ); if ( s ) gdome_str_unref( s ); if ( n ) gdome_n_unref( n, &exc ); if ( res ) gdome_xpresult_unref( res, &exc ); if ( doc ) gdome_doc_unref( doc, &exc ); return exc; } int test_relative( void ) { GdomeException exc = GDOME_NOEXCEPTION_ERR; GdomeDocument *doc = NULL; GdomeXPathResult *res = NULL, *res2 = NULL; GdomeNode *n = NULL, *n2 = NULL; GdomeDOMString *s=NULL, *s2 = NULL; unsigned i = 0, j = 0; res = xpath_xml( "//ns:a/ns:b", "ns", uri, xml, doc, &exc ); if ( exc ) goto clean_up; g_assert( res ); while ( ( n = gdome_xpresult_iterateNext( res, &exc ) ) != NULL ) { s = gdome_n_nodeName( n, &exc ); if ( exc ) goto clean_up; g_assert( strcmp( s->str, "b" ) == 0 ); gdome_str_unref( s ); s = NULL; res2 = xpath_node( "ns:p[@attr=\"name2\"]/text()", "ns", uri, n, &exc ); if ( exc ) goto clean_up; g_assert( res2 ); while ( ( n2 = gdome_xpresult_iterateNext( res2, &exc ) ) != NULL ) { s2 = gdome_t_data( (GdomeText*)n2, &exc ); if ( exc ) goto clean_up; g_assert( strcmp( s2->str, "value1.2" ) == 0 ); gdome_str_unref( s2 ); s2 = NULL; gdome_n_unref( n2, &exc ); if ( exc ) goto clean_up; n2 = NULL; j ++; } gdome_n_unref( n, &exc ); if ( exc ) goto clean_up; n = NULL; i++; } g_assert( i == 1 ); g_assert( j == 1 ); clean_up: if ( exc ) fprintf( stderr, "Exception: %d\n", exc ); if ( s ) gdome_str_unref( s ); if ( s2 ) gdome_str_unref( s2 ); if ( n ) gdome_n_unref( n, &exc ); if ( n2 ) gdome_n_unref( n2, &exc ); if ( res ) gdome_xpresult_unref( res, &exc ); if ( res2 ) gdome_xpresult_unref( res2, &exc ); if ( doc ) gdome_doc_unref( doc, &exc ); return exc; } int test_multiple( void ) { GdomeException exc = GDOME_NOEXCEPTION_ERR; GdomeDocument *doc = NULL; GdomeXPathResult *res = xpath_xml( "//ns:p[@attr=\"name1\"]/text()", "ns", uri, xml, doc, &exc ); GdomeNode *n = NULL; GdomeDOMString *s = NULL; static const char *values[] = { "value1.1", "value2" }; unsigned i = 0, max = 2; g_assert( res ); while ( ( n = gdome_xpresult_iterateNext( res, &exc ) ) != NULL ) { s = gdome_t_data( (GdomeText*)n, &exc ); if ( exc ) goto clean_up; g_assert( i < max ); g_assert( strcmp( s->str, values[ i ] ) == 0 ); gdome_str_unref( s ); s = NULL; gdome_n_unref( n, &exc ); if ( exc ) goto clean_up; n = NULL; i++; } g_assert( i == 2 ); clean_up: if ( exc ) fprintf( stderr, "Exception: %d\n", exc ); if ( s ) gdome_str_unref( s ); if ( n ) gdome_n_unref( n, &exc ); if ( res ) gdome_xpresult_unref( res, &exc ); if ( doc ) gdome_doc_unref( doc, &exc ); return exc; } int main( int argc, char *argv[] ) { test_root(); test_complete(); test_relative(); test_multiple(); return 0; } _______________________________________________ gdome mailing list gdome@... http://mail.gnome.org/mailman/listinfo/gdome |
| Free embeddable forum powered by Nabble | Forum Help |