]> mj.ucw.cz Git - libucw.git/commitdiff
XML: Bug fixes of namespaces
authorMartin Mares <mj@ucw.cz>
Fri, 13 Feb 2015 14:36:59 +0000 (15:36 +0100)
committerMartin Mares <mj@ucw.cz>
Fri, 13 Feb 2015 14:36:59 +0000 (15:36 +0100)
ucw-xml/common.c
ucw-xml/ns.c
ucw-xml/parse.c

index 5cfd8513579dfca5b382b41505e6684ae88f307c..8c23ce2a4b88bf7be2b99732bbd1fa28e96afe2c 100644 (file)
@@ -120,7 +120,8 @@ void
 xml_reset(struct xml_context *ctx)
 {
   TRACE(ctx, "reset");
-  struct mempool *pool = ctx->pool, *stack = ctx->stack;
+  struct mempool *pool = ctx->pool, *stack = ctx->stack, *ns_pool = ctx->ns_pool;
+  const char **ns_by_id = ctx->ns_by_id;
   xml_dtd_cleanup(ctx);
   xml_sources_cleanup(ctx);
   mp_flush(pool);
@@ -128,5 +129,7 @@ xml_reset(struct xml_context *ctx)
   *ctx = xml_defaults;
   ctx->pool = pool;
   ctx->stack = stack;
+  ctx->ns_pool = ns_pool;
+  ctx->ns_by_id = ns_by_id;
   xml_ns_reset(ctx);
 }
index 66a4fdbb5a6624c44bc67760f0b569d8fe20f800..18412ddda1c058060e8b400c1eb468164b273d55 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <ucw/lib.h>
 #include <ucw/gary.h>
+#include <ucw/string.h>
 #include <ucw-xml/xml.h>
 #include <ucw-xml/internals.h>
 
@@ -31,10 +32,10 @@ struct ns_hash_entry {
 #define HASH_NODE struct ns_hash_entry
 #define HASH_PREFIX(x) ns_hash_##x
 #define HASH_KEY_ENDSTRING name
-#define HASH_WANT_CLEANUP
 #define HASH_WANT_FIND
 #define HASH_WANT_LOOKUP
 #define HASH_TABLE_DYNAMIC
+#define HASH_TABLE_ALLOC
 #define HASH_LOOKUP_DETECT_NEW
 #define HASH_GIVE_ALLOC
 XML_HASH_GIVE_ALLOC
@@ -60,9 +61,11 @@ xml_ns_enable(struct xml_context *ctx)
     return;
 
   TRACE(ctx, "NS: Enabling");
+  ASSERT(!ctx->depth);
   ctx->flags |= XML_NAMESPACES;
   if (!ctx->ns_pool)
     {
+      // CAVEAT: xml_reset() must handle everything we allocate here
       TRACE(ctx, "NS: Allocating data structures");
       ctx->ns_pool = mp_new(4096);
       GARY_INIT(ctx->ns_by_id, 16);
@@ -95,8 +98,6 @@ xml_ns_cleanup(struct xml_context *ctx)
     return;
 
   TRACE(ctx, "NS: Cleanup");
-  ns_hash_cleanup(ctx->ns_by_prefix);
-  ns_hash_cleanup(ctx->ns_by_name);
   GARY_FREE(ctx->ns_by_id);
   mp_delete(ctx->ns_pool);
 }
@@ -108,21 +109,23 @@ xml_ns_reset(struct xml_context *ctx)
     return;
 
   TRACE(ctx, "NS: Reset");
-  GARY_RESIZE(ctx->ns_by_id, 1);
-  ctx->ns_by_id[0] = "";
+  GARY_RESIZE(ctx->ns_by_id, 0);
   mp_flush(ctx->ns_pool);
 }
 
 const char *
 xml_ns_by_id(struct xml_context *ctx, uint ns)
 {
-  ASSERT(ns < GARY_SIZE(ctx->ns_by_id));
+  if (!ns)             // This should work even if namespaces are disabled
+    return "";
+  ASSERT(ns_enabled(ctx) && ns < GARY_SIZE(ctx->ns_by_id));
   return ctx->ns_by_id[ns];
 }
 
 uint
 xml_ns_by_name(struct xml_context *ctx, const char *name)
 {
+  ASSERT(ns_enabled(ctx));
   int new_p;
   struct ns_hash_entry *he = ns_hash_lookup(ctx->ns_by_name, (char *) name, &new_p);
   if (new_p)
@@ -181,10 +184,10 @@ void xml_ns_push_element(struct xml_context *ctx)
 
   /* Scan attributes for prefix definitions */
   XML_ATTR_FOR_EACH(a, e)
-    if (!memcmp(a->name, "xmlns", 5))
+    if (str_has_prefix(a->name, "xmlns"))
       {
        uint ns = xml_ns_by_name(ctx, a->val);
-       if (a->name[5] == ':' && a->name[6])
+       if (a->name[5] == ':')
          {
            if (!ns)
              xml_error(ctx, "Namespace prefixes must not be undeclared");
index 2ddfa2b8fac52106e6169b9afa66a8423d40ee6b..b1790d0b7081303954b0455c57123c611a44551c 100644 (file)
@@ -850,7 +850,7 @@ xml_parse_etag(struct xml_context *ctx)
   if (xml_get_char(ctx) != '>')
     {
 recover:
-      xml_error(ctx, "Invalid ETag, expected </%s>", e->name);
+      xml_error(ctx, "Invalid ETag, expected </%s>", xml_node_qname(ctx, e));
       while (xml_get_char(ctx) != '>');
     }
   xml_dec(ctx);