Commit 84ca33a7 authored by Greg Stein's avatar Greg Stein
Browse files

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
parent 1184b275
Loading
Loading
Loading
Loading
+43 −0
Original line number Diff line number Diff line
@@ -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);

/* --------------------------------------------------------------------
**
+65 −0
Original line number Diff line number Diff line
@@ -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