diff --git a/include/asterisk/xml.h b/include/asterisk/xml.h index d80fb26f78..722155848c 100644 --- a/include/asterisk/xml.h +++ b/include/asterisk/xml.h @@ -82,6 +82,23 @@ struct ast_xml_node *ast_xml_new_child(struct ast_xml_node *parent, const char * */ struct ast_xml_node *ast_xml_add_child(struct ast_xml_node *parent, struct ast_xml_node *child); +/*! + * \brief Add a list of child nodes, to a specified parent node. + * \param parent Where to add the child node. + * \param child The child list to add. + * \retval NULL on error. + * \retval non-NULL The added child list on success. + */ +struct ast_xml_node *ast_xml_add_child_list(struct ast_xml_node *parent, struct ast_xml_node *child); + +/*! + * \brief Create a copy of a n ode list. + * \param list The list to copy. + * \retval NULL on error. + * \retval non-NULL The copied list. + */ +struct ast_xml_node *ast_xml_copy_node_list(struct ast_xml_node *list); + /*! * \brief Close an already open document and free the used * structure. diff --git a/main/xml.c b/main/xml.c index 46fe198e4c..2bcda80d89 100644 --- a/main/xml.c +++ b/main/xml.c @@ -144,6 +144,22 @@ struct ast_xml_node *ast_xml_add_child(struct ast_xml_node *parent, struct ast_x return (struct ast_xml_node *) xmlAddChild((xmlNode *) parent, (xmlNode *) child); } +struct ast_xml_node *ast_xml_add_child_list(struct ast_xml_node *parent, struct ast_xml_node *child) +{ + if (!parent || !child) { + return NULL; + } + return (struct ast_xml_node *) xmlAddChildList((xmlNode *) parent, (xmlNode *) child); +} + +struct ast_xml_node *ast_xml_copy_node_list(struct ast_xml_node *list) +{ + if (!list) { + return NULL; + } + return (struct ast_xml_node *) xmlCopyNodeList((xmlNode *) list); +} + struct ast_xml_doc *ast_xml_read_memory(char *buffer, size_t size) { xmlDoc *doc; diff --git a/main/xmldoc.c b/main/xmldoc.c index 86ccec020d..d24245334a 100644 --- a/main/xmldoc.c +++ b/main/xmldoc.c @@ -2785,6 +2785,8 @@ static int xml_pathmatch(char *xmlpattern, int xmlpattern_maxlen, glob_t *globbu static char *handle_dump_docs(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { struct documentation_tree *doctree; + struct ast_xml_doc *dumpdoc; + struct ast_xml_node *dumproot; FILE *f; switch (cmd) { @@ -2801,15 +2803,53 @@ static char *handle_dump_docs(struct ast_cli_entry *e, int cmd, struct ast_cli_a if (a->argc != 3) { return CLI_SHOWUSAGE; } - if (!(f = fopen(a->argv[2], "w"))) { - ast_log(LOG_ERROR, "Could not open file '%s': %s\n", a->argv[2], strerror(errno)); + + dumpdoc = ast_xml_new(); + if (!dumpdoc) { + ast_log(LOG_ERROR, "Could not create new XML document\n"); + return CLI_FAILURE; + } + + dumproot = ast_xml_new_node("docs"); + if (!dumproot) { + ast_xml_close(dumpdoc); + ast_log(LOG_ERROR, "Could not create new XML root node\n"); return CLI_FAILURE; } + + ast_xml_set_root(dumpdoc, dumproot); + AST_RWLIST_RDLOCK(&xmldoc_tree); AST_LIST_TRAVERSE(&xmldoc_tree, doctree, entry) { - ast_xml_doc_dump_file(f, doctree->doc); + struct ast_xml_node *root_node = ast_xml_get_root(doctree->doc); + struct ast_xml_node *kids = ast_xml_node_get_children(root_node); + struct ast_xml_node *kids_copy; + + /* If there are no kids someone screwed up, but we check anyway. */ + if (!kids) { + continue; + } + + kids_copy = ast_xml_copy_node_list(kids); + if (!kids_copy) { + ast_xml_close(dumpdoc); + ast_log(LOG_ERROR, "Could not create copy of XML node list\n"); + return CLI_FAILURE; + } + + ast_xml_add_child_list(dumproot, kids_copy); } AST_RWLIST_UNLOCK(&xmldoc_tree); + + if (!(f = fopen(a->argv[2], "w"))) { + ast_xml_close(dumpdoc); + ast_log(LOG_ERROR, "Could not open file '%s': %s\n", a->argv[2], strerror(errno)); + return CLI_FAILURE; + } + + ast_xml_doc_dump_file(f, dumpdoc); + ast_xml_close(dumpdoc); + fclose(f); return CLI_SUCCESS; }