From f8a86a26c40cfbe8078c13e0bc874d3ba09bd97a Mon Sep 17 00:00:00 2001 From: Jonas Fonseca Date: Mon, 30 Jan 2006 06:07:16 +0100 Subject: [PATCH] DOM: Add simple stack context based utility for dumping DOM trees to SGML --- src/dom/sgml/Makefile | 2 +- src/dom/sgml/dump.c | 170 ++++++++++++++++++++++++++++++++++++++++++ src/dom/sgml/dump.h | 12 +++ 3 files changed, 183 insertions(+), 1 deletion(-) create mode 100644 src/dom/sgml/dump.c create mode 100644 src/dom/sgml/dump.h diff --git a/src/dom/sgml/Makefile b/src/dom/sgml/Makefile index 193145e92..581567aec 100644 --- a/src/dom/sgml/Makefile +++ b/src/dom/sgml/Makefile @@ -2,6 +2,6 @@ top_builddir=../../.. include $(top_builddir)/Makefile.config SUBDIRS = docbook html rss xbel -OBJS = sgml.o parser.o scanner.o +OBJS = dump.o parser.o scanner.o sgml.o include $(top_srcdir)/Makefile.lib diff --git a/src/dom/sgml/dump.c b/src/dom/sgml/dump.c new file mode 100644 index 000000000..902a7e4f3 --- /dev/null +++ b/src/dom/sgml/dump.c @@ -0,0 +1,170 @@ +/* SGML generics */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "elinks.h" + +#include "dom/node.h" +#include "dom/sgml/dump.h" +#include "dom/stack.h" +#include "dom/string.h" + + +static enum dom_stack_code +sgml_file_dumper_element_push(struct dom_stack *stack, struct dom_node *node, void *data) +{ + FILE *file = stack->current->data; + struct dom_string *string = &node->string; + + fprintf(file, "<%.*s", string->length, string->string); + if (!node->data.element.map + || node->data.element.map->size == 0) + fprintf(file, ">"); + + return DOM_STACK_CODE_OK; +} + +static enum dom_stack_code +sgml_file_dumper_element_pop(struct dom_stack *stack, struct dom_node *node, void *data) +{ + FILE *file = stack->current->data; + struct dom_string *string = &node->string; + + fprintf(file, "", string->length, string->string); + + return DOM_STACK_CODE_OK; +} + +static enum dom_stack_code +sgml_file_dumper_attribute_push(struct dom_stack *stack, struct dom_node *node, void *data) +{ + FILE *file = stack->current->data; + struct dom_string *name = &node->string; + struct dom_string *value = &node->data.attribute.value; + + if (node->parent->type == DOM_NODE_PROCESSING_INSTRUCTION) + return DOM_STACK_CODE_OK; + + fprintf(file, " %.*s", name->length, name->string); + + if (value->string) { + if (node->data.attribute.quoted) + fprintf(file, "=%c%.*s%c", + node->data.attribute.quoted, + value->length, value->string, + node->data.attribute.quoted); + else + /* FIXME: 'encode' if the value contains '"'s? */ + fprintf(file, "=\"%.*s\"", value->length, value->string); + } + + if (!get_dom_node_next(node)) + fprintf(file, ">"); + + return DOM_STACK_CODE_OK; +} + +static enum dom_stack_code +sgml_file_dumper_proc_instruction_push(struct dom_stack *stack, struct dom_node *node, void *data) +{ + FILE *file = stack->current->data; + struct dom_string *target = &node->string; + struct dom_string *instruction = &node->data.proc_instruction.instruction; + + fprintf(file, "", + target->length, target->string, + instruction->length, instruction->string); + + return DOM_STACK_CODE_OK; +} + +static enum dom_stack_code +sgml_file_dumper_text_push(struct dom_stack *stack, struct dom_node *node, void *data) +{ + FILE *file = stack->current->data; + struct dom_string *string = &node->string; + + fprintf(file, "%.*s", string->length, string->string); + + return DOM_STACK_CODE_OK; +} + +static enum dom_stack_code +sgml_file_dumper_cdata_section_push(struct dom_stack *stack, struct dom_node *node, void *data) +{ + FILE *file = stack->current->data; + struct dom_string *string = &node->string; + + fprintf(file, "", string->length, string->string); + + return DOM_STACK_CODE_OK; +} + +static enum dom_stack_code +sgml_file_dumper_comment_push(struct dom_stack *stack, struct dom_node *node, void *data) +{ + FILE *file = stack->current->data; + struct dom_string *string = &node->string; + + fprintf(file, "", string->length, string->string); + + return DOM_STACK_CODE_OK; +} + +static enum dom_stack_code +sgml_file_dumper_entity_ref_push(struct dom_stack *stack, struct dom_node *node, void *data) +{ + FILE *file = stack->current->data; + struct dom_string *string = &node->string; + + fprintf(file, "&%.*s;", string->length, string->string); + + return DOM_STACK_CODE_OK; +} + +struct dom_stack_context_info sgml_file_dumper = { + /* Object size: */ 0, + /* Push: */ + { + /* */ NULL, + /* DOM_NODE_ELEMENT */ sgml_file_dumper_element_push, + /* DOM_NODE_ATTRIBUTE */ sgml_file_dumper_attribute_push, + /* DOM_NODE_TEXT */ sgml_file_dumper_text_push, + /* DOM_NODE_CDATA_SECTION */ sgml_file_dumper_cdata_section_push, + /* DOM_NODE_ENTITY_REFERENCE */ sgml_file_dumper_entity_ref_push, + /* DOM_NODE_ENTITY */ NULL, + /* DOM_NODE_PROC_INSTRUCTION */ sgml_file_dumper_proc_instruction_push, + /* DOM_NODE_COMMENT */ sgml_file_dumper_comment_push, + /* DOM_NODE_DOCUMENT */ NULL, + /* DOM_NODE_DOCUMENT_TYPE */ NULL, + /* DOM_NODE_DOCUMENT_FRAGMENT */ NULL, + /* DOM_NODE_NOTATION */ NULL, + }, + /* Pop: */ + { + /* */ NULL, + /* DOM_NODE_ELEMENT */ sgml_file_dumper_element_pop, + /* DOM_NODE_ATTRIBUTE */ NULL, + /* DOM_NODE_TEXT */ NULL, + /* DOM_NODE_CDATA_SECTION */ NULL, + /* DOM_NODE_ENTITY_REFERENCE */ NULL, + /* DOM_NODE_ENTITY */ NULL, + /* DOM_NODE_PROC_INSTRUCTION */ NULL, + /* DOM_NODE_COMMENT */ NULL, + /* DOM_NODE_DOCUMENT */ NULL, + /* DOM_NODE_DOCUMENT_TYPE */ NULL, + /* DOM_NODE_DOCUMENT_FRAGMENT */ NULL, + /* DOM_NODE_NOTATION */ NULL, + } +}; + +struct dom_stack_context * +add_sgml_file_dumper(struct dom_stack *stack, FILE *file) +{ + return add_dom_stack_context(stack, file, &sgml_file_dumper); +} diff --git a/src/dom/sgml/dump.h b/src/dom/sgml/dump.h new file mode 100644 index 000000000..ac21a85ad --- /dev/null +++ b/src/dom/sgml/dump.h @@ -0,0 +1,12 @@ +#ifndef EL_DOM_SGML_DUMP_H +#define EL_DOM_SGML_DUMP_H + +#include + +struct dom_stack; +struct dom_stack_context; + +struct dom_stack_context * +add_sgml_file_dumper(struct dom_stack *stack, FILE *file); + +#endif