From: Greg Stein Date: Tue, 11 Sep 2001 12:29:28 +0000 (+0000) Subject: Add an opaque datatype for managing a set of XML namespace declarations. X-Git-Tag: 2.0.26~270 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=184f20d86e7bc52b58007e7d3c2945f93f69335b;p=apache Add an opaque datatype for managing a set of XML namespace declarations. Part of an upcoming propdb API improvement. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@91004 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/modules/dav/main/mod_dav.h b/modules/dav/main/mod_dav.h index de779730ca..fd707d0e10 100644 --- a/modules/dav/main/mod_dav.h +++ b/modules/dav/main/mod_dav.h @@ -529,6 +529,49 @@ ap_xml_elem *dav_find_child(const ap_xml_elem *elem, const char *tagname); const char *dav_xml_get_cdata(const ap_xml_elem *elem, apr_pool_t *pool, int strip_white); +/* +** XML namespace handling +** +** This structure tracks namespace declarations (xmlns:prefix="URI"). +** It maintains a many-to-one relationship of URIs-to-prefixes. In other +** words, a URI may be defined by multiple prefixes, but any specific +** prefix will specify only one URI. +** +** Prefixes using the "g###" pattern can be generated automatically if +** the caller does not have specific prefix requirements. +*/ +typedef struct { + apr_pool_t *pool; + apr_hash_t *uri_prefix; /* map URIs to an available prefix */ + apr_hash_t *prefix_uri; /* map all prefixes to their URIs */ + int count; /* counter for "g###" prefixes */ +} dav_xmlns_info; + +/* create an empty dav_xmlns_info structure */ +DAV_DECLARE(dav_xmlns_info *) dav_xmlns_create(apr_pool_t *pool); + +/* add a specific prefix/URI pair. the prefix/uri should have a lifetime + at least that of xmlns->pool */ +DAV_DECLARE(void) dav_xmlns_add(dav_xmlns_info *xi, + const char *prefix, const char *uri); + +/* add a URI (if not present); any prefix is acceptable and is returned. + the uri should have a lifetime at least that xmlns->pool */ +DAV_DECLARE(const char *) dav_xmlns_add_uri(dav_xmlns_info *xi, + const char *uri); + +/* return the URI for a specified prefix (or NULL if the prefix is unknown) */ +DAV_DECLARE(const char *) dav_xmlns_get_uri(dav_xmlns_info *xi, + const char *prefix); + +/* return an available prefix for a specified URI (or NULL if the URI + is unknown) */ +DAV_DECLARE(const char *) dav_xmlns_get_prefix(dav_xmlns_info *xi, + const char *uri); + +/* generate xmlns declarations (appending into the given text) */ +DAV_DECLARE(void) dav_xmlns_generate(dav_xmlns_info *xi, + apr_text_header *phdr); /* -------------------------------------------------------------------- ** diff --git a/modules/dav/main/util.c b/modules/dav/main/util.c index 01d345f253..1fda3b2699 100644 --- a/modules/dav/main/util.c +++ b/modules/dav/main/util.c @@ -400,6 +400,71 @@ const char *dav_xml_get_cdata(const ap_xml_elem *elem, apr_pool_t *pool, return cdata; } +DAV_DECLARE(dav_xmlns_info *) dav_xmlns_create(apr_pool_t *pool) +{ + dav_xmlns_info *xi = apr_pcalloc(pool, sizeof(*xi)); + + xi->uri_prefix = apr_hash_make(pool); + xi->prefix_uri = apr_hash_make(pool); + + return xi; +} + +DAV_DECLARE(void) dav_xmlns_add(dav_xmlns_info *xi, + const char *prefix, const char *uri) +{ + /* this "should" not overwrite a prefix mapping */ + apr_hash_set(xi->prefix_uri, prefix, APR_HASH_KEY_STRING, uri); + + /* note: this may overwrite an existing URI->prefix mapping, but it + doesn't matter -- any prefix is usuable to specify the URI. */ + apr_hash_set(xi->uri_prefix, uri, APR_HASH_KEY_STRING, prefix); +} + +DAV_DECLARE(const char *) dav_xmlns_add_uri(dav_xmlns_info *xi, + const char *uri) +{ + const char *prefix; + + if ((prefix = apr_hash_get(xi->uri_prefix, uri, + APR_HASH_KEY_STRING)) != NULL) + return prefix; + + prefix = apr_psprintf(xi->pool, "g%d", xi->count++); + dav_xmlns_add(xi, prefix, uri); + return prefix; +} + +DAV_DECLARE(const char *) dav_xmlns_get_uri(dav_xmlns_info *xi, + const char *prefix) +{ + return apr_hash_get(xi->prefix_uri, prefix, APR_HASH_KEY_STRING); +} + +DAV_DECLARE(const char *) dav_xmlns_get_prefix(dav_xmlns_info *xi, + const char *uri) +{ + return apr_hash_get(xi->uri_prefix, uri, APR_HASH_KEY_STRING); +} + +DAV_DECLARE(void) dav_xmlns_generate(dav_xmlns_info *xi, + apr_text_header *phdr) +{ + apr_hash_index_t *hi = apr_hash_first(xi->pool, xi->prefix_uri); + + for (; hi != NULL; hi = apr_hash_next(hi)) { + const void *prefix; + void *uri; + const char *s; + + apr_hash_this(hi, &prefix, NULL, &uri); + + s = apr_psprintf(xi->pool, " xmlns:%s=\"%s\"", + (const char *)prefix, (const char *)uri); + ap_text_append(xi->pool, phdr, s); + } +} + /* --------------------------------------------------------------- ** ** Timeout header processing