diff -r 5da2cf15eb44 -r b6f2462ee055 libidav/xml.c --- a/libidav/xml.c Mon Dec 18 16:24:32 2017 +0100 +++ b/libidav/xml.c Mon Jan 01 19:53:36 2018 +0100 @@ -30,6 +30,8 @@ #include #include +#include + #include "xml.h" static DavXmlNodeType convert_type(xmlElementType type) { @@ -135,6 +137,40 @@ } } +void dav_print_node(void *stream, write_func writef, UcxMap *nsmap, DavXmlNode *node) { + while(node) { + if(node->type == DAV_XML_ELEMENT) { + char *prefix = ucx_map_cstr_get(nsmap, node->namespace); + char *tagend = node->children ? ">" : " />"; + if(!prefix) { + sstr_t newpre = ucx_sprintf("x%d", (int)nsmap->count); + ucx_map_cstr_put(nsmap, node->namespace, newpre.ptr); + prefix = newpre.ptr; + ucx_fprintf( + stream, + writef, + "<%s:%s xmlns:%s=\"%s\"%s", + prefix, + node->name, + prefix, + node->namespace, + tagend); + } else { + ucx_fprintf(stream, writef, "<%s:%s%s", prefix, node->name, tagend); + } + + if(node->children) { + dav_print_node(stream, writef, nsmap, node->children); + ucx_fprintf(stream, writef, "", prefix, node->name); + } + } else if(node->type == DAV_XML_TEXT) { + writef(node->content, 1, node->contentlength, stream); + } + + node = node->next; + } +} + /* ------------------------- public API ------------------------- */ char* dav_xml_getstring(DavXmlNode *node) { @@ -163,3 +199,79 @@ return newxn; } + + + +DavXmlNode* dav_copy_node(DavXmlNode *node) { + DavXmlNode *ret = NULL; + DavXmlNode *prev = NULL; + while(node) { + DavXmlNode *copy = calloc(1, sizeof(DavXmlNode)); + copy->type = node->type; + if(node->type == DAV_XML_ELEMENT) { + copy->namespace = strdup(node->namespace); + copy->name = strdup(node->name); + copy->children = dav_copy_node(node->children); + } else { + copy->contentlength = node->contentlength; + copy->content = malloc(node->contentlength+1); + memcpy(copy->content, node->content, node->contentlength); + copy->content[copy->contentlength] = 0; + } + if(!ret) { + ret = copy; + } + if(prev) { + prev->next = copy; + copy->prev = prev; + } + prev = copy; + node = node->next; + } + return ret; +} + + +DavXmlNode* dav_xml_createnode(const char *ns, const char *name) { + DavXmlNode *node = calloc(1, sizeof(DavXmlNode)); + node->type = DAV_XML_ELEMENT; + node->namespace = strdup(ns); + node->name = strdup(name); + return node; +} + +DavXmlNode* dav_xml_createnode_with_text(const char *ns, const char *name, const char *text) { + DavXmlNode *node = calloc(1, sizeof(DavXmlNode)); + node->type = DAV_XML_ELEMENT; + node->namespace = strdup(ns); + node->name = strdup(name); + + DavXmlNode *textnode = dav_xml_createtextnode(text); + node->children = textnode; + + return node; +} + +DavXmlNode* dav_xml_createtextnode(const char *text) { + DavXmlNode *node = calloc(1, sizeof(DavXmlNode)); + node->type = DAV_XML_TEXT; + sstr_t content = sstrdup(sstr((char*)text)); + node->content = content.ptr; + node->contentlength = content.length; + return node; +} + +void dav_xml_add_child(DavXmlNode *node, DavXmlNode *child) { + DavXmlNode *last_child = NULL; + DavXmlNode *c = node->children; + while(c) { + last_child = c; + c = c->next; + } + if(last_child) { + last_child->next = child; + child->prev = last_child; + } else { + node->children = child; + } +}