diff options
author | Graham Leggett <minfrin@apache.org> | 2016-06-12 00:02:22 +0000 |
---|---|---|
committer | Graham Leggett <minfrin@apache.org> | 2016-06-12 00:02:22 +0000 |
commit | afb05ba52d4c344e41a43c54161943e36a84f37d (patch) | |
tree | 76c1c4a686d577de873916141230da100e5ec653 /xml | |
parent | 63225f69079607e4b3438c491629435d9256e07b (diff) | |
download | apr-afb05ba52d4c344e41a43c54161943e36a84f37d.tar.gz |
apr_xml_to_text: Add style APR_XML_X2T_PARSED to maintain a consistent namespace prefix.
git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@1747941 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'xml')
-rw-r--r-- | xml/apr_xml.c | 82 |
1 files changed, 76 insertions, 6 deletions
diff --git a/xml/apr_xml.c b/xml/apr_xml.c index 8ea2b32fe..82791f49d 100644 --- a/xml/apr_xml.c +++ b/xml/apr_xml.c @@ -97,6 +97,25 @@ static int find_prefix(apr_xml_parser *parser, const char *prefix) return APR_XML_NS_ERROR_UNKNOWN_PREFIX; } +/* return original prefix given ns index */ +static const char * find_prefix_name(const apr_xml_elem *elem, int ns, int parent) +{ + /* + ** Walk up the tree, looking for a namespace scope that defines this + ** prefix. + */ + for (; elem; elem = parent ? elem->parent : NULL) { + apr_xml_ns_scope *ns_scope = elem->ns_scope; + + for (; ns_scope; ns_scope = ns_scope->next) { + if (ns_scope->ns == ns) + return ns_scope->prefix; + } + } + /* not found */ + return ""; +} + static void start_handler(void *userdata, const char *name, const char **attrs) { apr_xml_parser *parser = userdata; @@ -538,7 +557,8 @@ static apr_size_t elem_size(const apr_xml_elem *elem, int style, { apr_size_t size; - if (style == APR_XML_X2T_FULL || style == APR_XML_X2T_FULL_NS_LANG) { + if (style == APR_XML_X2T_FULL || style == APR_XML_X2T_FULL_NS_LANG || + style == APR_XML_X2T_PARSED) { const apr_xml_attr *attr; size = 0; @@ -562,11 +582,29 @@ static apr_size_t elem_size(const apr_xml_elem *elem, int style, size += 11 + strlen(elem->lang) + 1; } } + else if (style == APR_XML_X2T_PARSED) { + apr_xml_ns_scope *ns_scope = elem->ns_scope; + + /* compute size of: ' xmlns:%s="%s"' */ + for (; ns_scope; ns_scope = ns_scope->next) { + size += 10 + strlen(find_prefix_name(elem, ns_scope->ns, 0)) + + strlen(APR_XML_GET_URI_ITEM(namespaces, ns_scope->ns)); + } + + if (elem->lang != NULL) { + /* compute size of: ' xml:lang="%s"' */ + size += 11 + strlen(elem->lang) + 1; + } + } if (elem->ns == APR_XML_NS_NONE) { /* compute size of: <%s> */ size += 1 + strlen(elem->name) + 1; } + else if (style == APR_XML_X2T_PARSED) { + /* compute size of: <%s:%s> */ + size += 3 + strlen(find_prefix_name(elem, elem->ns, 1)) + strlen(elem->name); + } else { int ns = ns_map ? ns_map[elem->ns] : elem->ns; @@ -592,6 +630,10 @@ static apr_size_t elem_size(const apr_xml_elem *elem, int style, /* compute size of: ' %s="%s"' */ size += 1 + strlen(attr->name) + 2 + strlen(attr->value) + 1; } + else if (style == APR_XML_X2T_PARSED) { + /* compute size of: ' %s:%s="%s"' */ + size += 5 + strlen(find_prefix_name(elem, attr->ns, 1)) + strlen(attr->name) + strlen(attr->value); + } else { /* compute size of: ' ns%d:%s="%s"' */ int ns = ns_map ? ns_map[attr->ns] : attr->ns; @@ -625,7 +667,7 @@ static apr_size_t elem_size(const apr_xml_elem *elem, int style, for (elem = elem->first_child; elem; elem = elem->next) { /* the size of the child element plus the CDATA that follows it */ - size += (elem_size(elem, APR_XML_X2T_FULL, NULL, ns_map) + + size += (elem_size(elem, style == APR_XML_X2T_PARSED ? APR_XML_X2T_PARSED : APR_XML_X2T_FULL, NULL, ns_map) + text_size(elem->following_cdata.first)); } @@ -649,13 +691,17 @@ static char *write_elem(char *s, const apr_xml_elem *elem, int style, apr_size_t len; int ns; - if (style == APR_XML_X2T_FULL || style == APR_XML_X2T_FULL_NS_LANG) { + if (style == APR_XML_X2T_FULL || style == APR_XML_X2T_FULL_NS_LANG || + style == APR_XML_X2T_PARSED) { int empty = APR_XML_ELEM_IS_EMPTY(elem); const apr_xml_attr *attr; if (elem->ns == APR_XML_NS_NONE) { len = sprintf(s, "<%s", elem->name); } + else if (style == APR_XML_X2T_PARSED) { + len = sprintf(s, "<%s:%s", find_prefix_name(elem, elem->ns, 1), elem->name); + } else { ns = ns_map ? ns_map[elem->ns] : elem->ns; len = sprintf(s, "<ns%d:%s", ns, elem->name); @@ -663,8 +709,13 @@ static char *write_elem(char *s, const apr_xml_elem *elem, int style, s += len; for (attr = elem->attr; attr; attr = attr->next) { - if (attr->ns == APR_XML_NS_NONE) + if (attr->ns == APR_XML_NS_NONE) { len = sprintf(s, " %s=\"%s\"", attr->name, attr->value); + } + else if (style == APR_XML_X2T_PARSED) { + len = sprintf(s, " %s:%s=\"%s\"", + find_prefix_name(elem, attr->ns, 1), attr->name, attr->value); + } else { ns = ns_map ? ns_map[attr->ns] : attr->ns; len = sprintf(s, " ns%d:%s=\"%s\"", ns, attr->name, attr->value); @@ -692,6 +743,19 @@ static char *write_elem(char *s, const apr_xml_elem *elem, int style, } } + else if (style == APR_XML_X2T_PARSED) { + apr_xml_ns_scope *ns_scope = elem->ns_scope; + + for (; ns_scope; ns_scope = ns_scope->next) { + const char *prefix = find_prefix_name(elem, ns_scope->ns, 0); + + len = sprintf(s, " xmlns%s%s=\"%s\"", + *prefix ? ":" : "", *prefix ? prefix : "", + APR_XML_GET_URI_ITEM(namespaces, ns_scope->ns)); + s += len; + } + } + /* no more to do. close it up and go. */ if (empty) { *s++ = '/'; @@ -715,14 +779,20 @@ static char *write_elem(char *s, const apr_xml_elem *elem, int style, s = write_text(s, elem->first_cdata.first); for (child = elem->first_child; child; child = child->next) { - s = write_elem(s, child, APR_XML_X2T_FULL, NULL, ns_map); + s = write_elem(s, child, + style == APR_XML_X2T_PARSED ? APR_XML_X2T_PARSED : APR_XML_X2T_FULL, + NULL, ns_map); s = write_text(s, child->following_cdata.first); } - if (style == APR_XML_X2T_FULL || style == APR_XML_X2T_FULL_NS_LANG) { + if (style == APR_XML_X2T_FULL || style == APR_XML_X2T_FULL_NS_LANG || + style == APR_XML_X2T_PARSED) { if (elem->ns == APR_XML_NS_NONE) { len = sprintf(s, "</%s>", elem->name); } + else if (style == APR_XML_X2T_PARSED) { + len = sprintf(s, "</%s:%s>", find_prefix_name(elem, elem->ns, 1), elem->name); + } else { ns = ns_map ? ns_map[elem->ns] : elem->ns; len = sprintf(s, "</ns%d:%s>", ns, elem->name); |