diff --git a/include/apr_xml.h b/include/apr_xml.h
index 2a43b28..4a46d1e 100644
--- a/include/apr_xml.h
+++ b/include/apr_xml.h
@@ -292,6 +292,7 @@ APU_DECLARE(void) apr_xml_to_text(apr_pool_t *p, const apr_xml_elem *elem,
 #define APR_XML_X2T_INNER        1	/**< contents only */
 #define APR_XML_X2T_LANG_INNER   2	/**< xml:lang + inner contents */
 #define APR_XML_X2T_FULL_NS_LANG 3	/**< FULL + ns defns + xml:lang */
+#define APR_XML_X2T_PARSED       4	/**< original prefixes */
 
 /**
  * empty XML element
diff --git a/xml/apr_xml.c b/xml/apr_xml.c
index b3ec875..a5caa72 100644
--- a/xml/apr_xml.c
+++ b/xml/apr_xml.c
@@ -86,7 +86,7 @@ static int find_prefix(apr_xml_parser *parser, const char *prefix)
     ** prefix.
     */
     for (; elem; elem = elem->parent) {
-	apr_xml_ns_scope *ns_scope = elem->ns_scope;
+	apr_xml_ns_scope *ns_scope;
 
 	for (ns_scope = elem->ns_scope; ns_scope; ns_scope = ns_scope->next) {
 	    if (strcmp(prefix, ns_scope->prefix) == 0) {
@@ -120,6 +120,26 @@ 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;
@@ -646,7 +666,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;
@@ -670,11 +691,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;
 
@@ -700,6 +739,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;
@@ -733,7 +776,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));
     }
 
@@ -757,13 +800,15 @@ 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) {
+	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);
@@ -773,10 +818,13 @@ static char *write_elem(char *s, const apr_xml_elem *elem, int style,
 	for (attr = elem->attr; attr; attr = attr->next) {
 	    if (attr->ns == APR_XML_NS_NONE)
 		len = sprintf(s, " %s=\"%s\"", 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);
-            }
+	    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);
+	    }
 	    s += len;
 	}
 
@@ -799,6 +847,18 @@ static char *write_elem(char *s, const apr_xml_elem *elem, int style,
 		s += len;
 	    }
 	}
+	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) {
@@ -823,14 +883,17 @@ 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 (elem->ns == APR_XML_NS_NONE) {
+    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);

