xml FEATURE allow dumping XML trees into file descriptor
diff --git a/src/xml.c b/src/xml.c
index 9415a40..d897e9e 100644
--- a/src/xml.c
+++ b/src/xml.c
@@ -29,6 +29,7 @@
#include "common.h"
#include "dict.h"
+#include "printer.h"
#include "tree_schema.h"
#include "xml_private.h"
@@ -1201,24 +1202,24 @@
}
static int
-dump_text(FILE * f, const char *text)
+dump_text(struct lyout *out, const char *text)
{
unsigned int i, n;
for (i = n = 0; text[i]; i++) {
switch (text[i]) {
case '&':
- n += fprintf(f, "&");
+ n += ly_print(out, "&");
break;
case '<':
- n += fprintf(f, "<");
+ n += ly_print(out, "<");
break;
case '>':
/* not needed, just for readability */
- n += fprintf(f, ">");
+ n += ly_print(out, ">");
break;
default:
- fputc(text[i], f);
+ ly_write(out, &text[i], 1);
n++;
}
}
@@ -1227,7 +1228,7 @@
}
static int
-dump_elem(FILE * f, struct lyxml_elem *e, int level, int options)
+dump_elem(struct lyout *out, struct lyxml_elem *e, int level, int options)
{
int size = 0;
struct lyxml_attr *a;
@@ -1238,7 +1239,7 @@
if (!e->name) {
/* mixed content */
if (e->content) {
- return dump_text(f, e->content);
+ return dump_text(out, e->content);
} else {
return 0;
}
@@ -1257,9 +1258,9 @@
if (!options || (options & LYXML_DUMP_OPEN)) {
/* opening tag */
if (e->ns && e->ns->prefix) {
- size += fprintf(f, "%*s<%s:%s", indent, "", e->ns->prefix, e->name);
+ size += ly_print(out, "%*s<%s:%s", indent, "", e->ns->prefix, e->name);
} else {
- size += fprintf(f, "%*s<%s", indent, "", e->name);
+ size += ly_print(out, "%*s<%s", indent, "", e->name);
}
} else if (options & LYXML_DUMP_CLOSE) {
indent = 0;
@@ -1270,69 +1271,89 @@
for (a = e->attr; a; a = a->next) {
if (a->type == LYXML_ATTR_NS) {
if (a->name) {
- size += fprintf(f, " xmlns:%s=\"%s\"", a->name, a->value ? a->value : "");
+ size += ly_print(out, " xmlns:%s=\"%s\"", a->name, a->value ? a->value : "");
} else {
- size += fprintf(f, " xmlns=\"%s\"", a->value ? a->value : "");
+ size += ly_print(out, " xmlns=\"%s\"", a->value ? a->value : "");
}
} else if (a->ns && a->ns->prefix) {
- size += fprintf(f, " %s:%s=\"%s\"", a->ns->prefix, a->name, a->value);
+ size += ly_print(out, " %s:%s=\"%s\"", a->ns->prefix, a->name, a->value);
} else {
- size += fprintf(f, " %s=\"%s\"", a->name, a->value);
+ size += ly_print(out, " %s=\"%s\"", a->name, a->value);
}
}
/* apply options */
if (options == (LYXML_DUMP_OPEN | LYXML_DUMP_CLOSE)) {
- size += fprintf(f, "/>%s", delim);
+ size += ly_print(out, "/>%s", delim);
return size;
} else if (options & LYXML_DUMP_OPEN) {
- fputc('>', f);
+ ly_print(out, ">");
return ++size;
} else if (options & LYXML_DUMP_ATTRS) {
return size;
}
if (!e->child && !e->content) {
- size += fprintf(f, "/>%s", delim);
+ size += ly_print(out, "/>%s", delim);
return size;
} else if (e->content) {
- fputc('>', f);
+ ly_print(out, ">");
size++;
- size += dump_text(f, e->content);
+ size += dump_text(out, e->content);
if (e->ns && e->ns->prefix) {
- size += fprintf(f, "</%s:%s>%s", e->ns->prefix, e->name, delim);
+ size += ly_print(out, "</%s:%s>%s", e->ns->prefix, e->name, delim);
} else {
- size += fprintf(f, "</%s>%s", e->name, delim);
+ size += ly_print(out, "</%s>%s", e->name, delim);
}
return size;
} else {
- size += fprintf(f, ">%s", delim);
+ size += ly_print(out, ">%s", delim);
}
/* go recursively */
LY_TREE_FOR(e->child, child) {
- size += dump_elem(f, child, level + 1, 0);
+ size += dump_elem(out, child, level + 1, 0);
}
close:
/* closing tag */
if (e->ns && e->ns->prefix) {
- size += fprintf(f, "%*s</%s:%s>%s", indent, "", e->ns->prefix, e->name, delim_outer);
+ size += ly_print(out, "%*s</%s:%s>%s", indent, "", e->ns->prefix, e->name, delim_outer);
} else {
- size += fprintf(f, "%*s</%s>%s", indent, "", e->name, delim_outer);
+ size += ly_print(out, "%*s</%s>%s", indent, "", e->name, delim_outer);
}
return size;
}
API int
-lyxml_dump(FILE * stream, struct lyxml_elem *elem, int options)
+lyxml_dump(FILE *stream, struct lyxml_elem *elem, int options)
{
- if (!elem) {
+ struct lyout out;
+
+ if (!stream || !elem) {
return 0;
}
- return dump_elem(stream, elem, 0, options);
+ out.type = LYOUT_STREAM;
+ out.method.f = stream;
+
+ return dump_elem(&out, elem, 0, options);
+}
+
+API int
+lyxml_dump_fd(int fd, struct lyxml_elem *elem, int options)
+{
+ struct lyout out;
+
+ if (fd < 0 || !elem) {
+ return 0;
+ }
+
+ out.type = LYOUT_FD;
+ out.method.fd = fd;
+
+ return dump_elem(&out, elem, 0, options);
}
diff --git a/src/xml.h b/src/xml.h
index b36b419..45c459c 100644
--- a/src/xml.h
+++ b/src/xml.h
@@ -165,6 +165,8 @@
/**
* @brief Dump XML tree to a IO stream
*
+ * To write data into a file descriptor instead of file stream, use lyxml_dump_fd().
+ *
* @param[in] stream IO stream to print out the tree.
* @param[in] elem Root element of the XML tree to print
* @param[in] options Dump options, see @ref xmldumpoptions.
@@ -174,6 +176,19 @@
int lyxml_dump(FILE * stream, struct lyxml_elem *elem, int options);
/**
+ * @brief Dump XML tree to a IO stream
+ *
+ * Same as lyxml_dump(), but it writes data into the given file descriptor.
+ *
+ * @param[in] fd File descriptor to print out the tree.
+ * @param[in] elem Root element of the XML tree to print
+ * @param[in] options Dump options, see @ref xmldumpoptions.
+ * @return number of printed characters.
+ *
+ */
+int lyxml_dump_fd(int fd, struct lyxml_elem *elem, int options);
+
+/**
* @brief Free (and unlink from the XML tree) the specified element with all
* its attributes and namespace definitions.
*