[gdome] Fix for XPath with default namespace
- From: Gustavo Sverzut Barbieri <Gustavo Barbieri indt org br>
- To: gdome gnome org
- Cc: eduardo lima indt org br, renato chencarek indt org br, eduardo rocha indt org br
- Subject: [gdome] Fix for XPath with default namespace
- Date: Fri, 31 Mar 2006 17:35:11 -0300
This 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 gmail com
MSN: barbieri gmail com
ICQ#: 17249123
Skype: gsbarbieri
Mobile: +55 (81) 9927 0010
Phone: +1 (347) 624 6296; 08122692 sip stanaphone com
GPG: 0xB640E1A2 @ wwwkeys.pgp.net
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;
#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;
}
[
Date Prev][Date Next] [
Thread Prev][Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]