#define USE_XML_ATTR_DATA
#include <xml/dumptree.h>
#include <xml/attrnode.h>
#include <xml/attrdata.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>

#include <stdio.h>
#include <string.h>
#include <errno.h>

#ifndef STDOUT_FILENO
#define STDOUT_FILENO 1
#endif

#define ___ {
#define ____ }

typedef struct 
{
    GString* str;
    int flag;
}
 Data;
static void attr_list_string_append (GString* g, xml_AttrList* list, int flag)
{
    for (; list ; list = list->next)
    
{
	register gchar* name = list->data->name;
        if (*name == ' ') continue;
	if (!(XML_G_WITH_HIDDEN&flag) && !g_ascii_isalnum(*name)) continue;
        xml_attr_data_string_append (g, list->data);
    }
}
GString*
xml_tree_dump_to_xml (xml_GNode* node, GString* g, int flag)
{
    if (! g) g = g_string_new(0);

    if (node->name)
    
{
        switch (node->name[0])
	
{
	case '<':
            g_string_append (g, node->name);
	    break;
	case '-':
	    if (!(XML_G_WITH_HIDDEN&flag)) goto done;
	case ':':
	    if (! node->name[1]) break;
	    /*fallthrough*/
	default:
            g_string_append_c (g, '<');
            g_string_append (g, node->name);
	    attr_list_string_append (g, node->attributes, flag);
	    if (node->end != node->off || !(XML_G_EMPTY_NODES&flag))
                g_string_append_c (g, '>');
	    else
		g_string_append (g, " />");
	    break;
        }
}
if (node->children)
{
        xml_GNode* child = node->children;
        xml_GNode* print = 0;
                  
        for (; child ; child = child->next)
        
{
            if (child->text)
            
{ /* the text between nodes or just before */
                if (print)
                    xml_g_string_append (g,
		      print->text->str + print->end, child->off - print->end);
                else if (node->text)
                    xml_g_string_append (g, 
                      node->text->str + node->off, child->off - node->off);
                    print = child;
            }
xml_tree_dump_to_xml (child, g, flag); }
if (node->text)
{  /* text after or just the full of it */
            if (print) 
                xml_g_string_append (g,
                  node->text->str + print->end, node->end - print->end);
            else
                xml_g_string_append (g,
                  node->text->str + node->off,  node->end - node->off);
        }
}
else
{
        if (node->text)
            xml_g_string_append (g, 
              node->text->str + node->off,  node->end - node->off);
    }
if (! node->name) goto done; if (node->name[0] == '<') goto done; if (node->name[0] == ':' && ! node->name[1]) goto done; if (node->end != node->off || !(XML_G_EMPTY_NODES&flag))
{
	g_string_append (g, "</");
	g_string_append (g, node->name);
	g_string_append_c (g, '>');
    }
done: return g; }
gboolean
xml_tree_dump_to_xml_file (xml_GNode* node, const gchar* file, int flag)
{
    if (! node) return FALSE;

    ___ int f;
    if (! file) 
{
	f = STDOUT_FILENO;
    }
else
{
	f = open (file, O_WRONLY|O_TRUNC|O_CREAT, 0666);
	if (f == -1) return FALSE;
    }
___ GString* g = 0; if (XML_G_TREE_ONLY&flag)
{
	if (XML_G_NODES_INFO&flag) g = g_string_new(0);
	g = xml_tree_dump_node_append (g, node);
    }
else
{
	g = xml_tree_dump_to_xml (node, 0, flag);
    }
if (! g || ! g->str)
{ 
	if (XML_G_WARNINGS&flag)
	    g_warning ("could not dump tree from internals"); 
        return FALSE;
    }
write (f, g->str, g->len); if (file) close (f); g_string_free (g, 1); return TRUE; ____;____; }
/* a convenience routine */
int
xml_tree_dump_to_xml_flags (const gchar* styleflag)
{
    int style = 0;
    if (strstr (styleflag, "-hidden"))  style |= XML_G_WITH_HIDDEN;
    if (strstr (styleflag, "-empty"))   style |= XML_G_EMPTY_NODES;
    if (strstr (styleflag, "-tree"))    style |= XML_G_TREE_ONLY;
    if (strstr (styleflag, "-nodes"))   style |= XML_G_NODES_INFO;
    return style;
}
/* 
   Local variables:
   c-file-style: "stroustrup"
   End:
 */