From f830ffd6a5a24b6b6ee18b73277f09abd881c860 Mon Sep 17 00:00:00 2001
From: Michael R Sweet
Date: Wed, 4 Jun 2003 17:37:23 +0000
Subject: [PATCH] Add mxmlAdd() and mxmlRemove() functions.
Documentation updates.
General cleanup.
---
CHANGES | 14 ++++-
README | 26 +++++++--
index.html | 27 +++++++--
mxml-file.c | 61 +++++++++++++++----
mxml-node.c | 165 ++++++++++++++++++++++++++++++++++++++++++----------
mxml.h | 21 +++++--
mxmldoc.c | 75 +++++++-----------------
testmxml.c | 56 +++++++++++++++---
8 files changed, 327 insertions(+), 118 deletions(-)
diff --git a/CHANGES b/CHANGES
index d603494..ea4b620 100644
--- a/CHANGES
+++ b/CHANGES
@@ -4,9 +4,13 @@ README - 06/04/2003
CHANGES IN Mini-XML 0.93
+ - Added mxmlAdd() and mxmlRemove() functions to add and
+ remove nodes from a tree. This provides more
+ flexibility over where the nodes are inserted and
+ allows nodes to be moved within the tree as needed.
- mxmlLoadFile() now correctly handles comments.
- - mxmlLoadFile() now supports the "gt" and "nbsp"
- character entities.
+ - mxmlLoadFile() now supports the required "gt", "quot",
+ and "nbsp" character entities.
- mxmlSaveFile() now uses newlines as whitespace
when valid to do so.
- mxmlFindElement() now also takes attribute name and
@@ -19,7 +23,11 @@ CHANGES IN Mini-XML 0.93
now all provide "descend" arguments to control whether
they descend into child nodes in the tree.
- Fixed some whitespace issues in mxmlLoadFile().
- - Fixed Unicode output issues in mxmlSaveFile().
+ - Fixed Unicode output and whitespace issues in
+ mxmlSaveFile().
+ - mxmlSaveFile() now supports a whitespace callback to
+ provide more human-readable XML output under program
+ control.
CHANGES IN Mini-XML 0.92
diff --git a/README b/README
index 61a51b1..151f6b9 100644
--- a/README
+++ b/README
@@ -13,9 +13,27 @@ INTRODUCTION
requires an ANSI C compatible compiler (GCC works, as do
most vendors' ANSI C compilers) and a "make" program.
- Mini-XML was created to support the basic hierarchy provided
- by XML and some simple data types, but doesn't do validation
- or other types of processing on the data.
+ Mini-XML provides the following functionality:
+
+ - Reading and writing of UTF-8 encoded XML files.
+ - Data is stored in a linked-list tree structure,
+ preserving the XML data hierarchy.
+ - Supports arbitrary element names, attributes, and
+ attribute values with no preset limits, just available
+ memory.
+ - Supports integer, real, opaque ("cdata"), and text
+ data types in "leaf" nodes.
+ - Functions for creating and managing trees of data.
+ - "Find" and "walk" functions for easily locating and
+ navigating trees of data.
+
+ Mini-XML doesn't do validation or other types of processing
+ on the data based upon schema files or other sources of
+ definition information, nor does it support character
+ entities other than those required by the XML
+ specification. Also, since Mini-XML does not support the
+ UTF-16 encoding, it is technically not a conforming XML
+ consumer/client.
BUILDING Mini-XML
@@ -86,7 +104,7 @@ DOCUMENTATION
mxml_node_t *tree;
fp = fopen("filename.xml", "w");
- mxmlSaveFile(tree, fp);
+ mxmlSaveFile(tree, fp, MXML_NO_CALLBACK);
fclose(fp);
You can find a named element/node using the
diff --git a/index.html b/index.html
index c147f4f..690a1f6 100644
--- a/index.html
+++ b/index.html
@@ -29,9 +29,28 @@ requiring large non-standard libraries. Mini-XML only requires
an ANSI C compatible compiler (GCC works, as do most vendors'
ANSI C compilers) and a "make" program.
-Mini-XML was created to support the basic hierarchy provided
-by XML and some simple data types, but doesn't do validation or
-other types of processing on the data.
+Mini-XML provides the following functionality:
+
+
+ - Reading and writing of UTF-8 encoded XML files.
+ - Data is stored in a linked-list tree structure,
+ preserving the XML data hierarchy.
+ - Supports arbitrary element names, attributes, and
+ attribute values with no preset limits, just available
+ memory.
+ - Supports integer, real, opaque ("cdata"), and text
+ data types in "leaf" nodes.
+ - Functions for creating and managing trees of data.
+ - "Find" and "walk" functions for easily locating and
+ navigating trees of data.
+
+
+Mini-XML doesn't do validation or other types of processing
+on the data based upon schema files or other sources of
+definition information, nor does it support character entities
+other than those required by the XML specification. Also, since
+Mini-XML does not support the UTF-16 encoding, it is technically
+not a conforming XML consumer/client.
Building Mini-XML
@@ -113,7 +132,7 @@ function:
mxml_node_t *tree;
fp = fopen("filename.xml", "w");
- mxmlSaveFile(tree, fp);
+ mxmlSaveFile(tree, fp, MXML_NO_CALLBACK);
fclose(fp);
diff --git a/mxml-file.c b/mxml-file.c
index 19ab436..74907ae 100644
--- a/mxml-file.c
+++ b/mxml-file.c
@@ -1,5 +1,5 @@
/*
- * "$Id: mxml-file.c,v 1.6 2003/06/04 16:30:40 mike Exp $"
+ * "$Id: mxml-file.c,v 1.7 2003/06/04 17:37:23 mike Exp $"
*
* File loading code for mini-XML, a small XML-like file parsing library.
*
@@ -36,7 +36,8 @@
*/
static int mxml_parse_element(mxml_node_t *node, FILE *fp);
-static int mxml_write_node(mxml_node_t *node, FILE *fp, int col);
+static int mxml_write_node(mxml_node_t *node, FILE *fp,
+ int (*cb)(mxml_node_t *, int), int col);
static int mxml_write_string(const char *s, FILE *fp);
@@ -367,7 +368,7 @@ mxmlLoadFile(mxml_node_t *top, /* I - Top node */
{
/*
* Add character entity to current buffer... Currently we only
- * support <, &, >, , nnn;, and XXXX;...
+ * support <, &, >, , ", nnn;, and XXXX;...
*/
char entity[64], /* Entity string */
@@ -413,6 +414,8 @@ mxmlLoadFile(mxml_node_t *top, /* I - Top node */
ch = '<';
else if (!strcmp(entity, " "))
ch = 0xa0;
+ else if (!strcmp(entity, """))
+ ch = '\"';
else
{
fprintf(stderr, "Entity name \"%s;\" not supported under parent <%s>!\n",
@@ -507,17 +510,23 @@ mxmlLoadFile(mxml_node_t *top, /* I - Top node */
int /* O - 0 on success, -1 on error */
mxmlSaveFile(mxml_node_t *node, /* I - Node to write */
- FILE *fp) /* I - File to write to */
+ FILE *fp, /* I - File to write to */
+ int (*cb)(mxml_node_t *, int))
+ /* I - Whitespace callback */
{
+ int col; /* Final column */
+
+
/*
* Write the node...
*/
- if (mxml_write_node(node, fp, 0) < 0)
+ if ((col = mxml_write_node(node, fp, cb, 0)) < 0)
return (-1);
- if (putc('\n', fp) < 0)
- return (-1);
+ if (col > 0)
+ if (putc('\n', fp) < 0)
+ return (-1);
/*
* Return 0 (success)...
@@ -688,9 +697,12 @@ mxml_parse_element(mxml_node_t *node, /* I - Element node */
static int /* O - Column or -1 on error */
mxml_write_node(mxml_node_t *node, /* I - Node to write */
FILE *fp, /* I - File to write to */
+ int (*cb)(mxml_node_t *, int),
+ /* I - Whitespace callback */
int col) /* I - Current column */
{
int i; /* Looping var */
+ int ch; /* Whitespace character */
int n; /* Chars written */
mxml_attr_t *attr; /* Current attribute */
@@ -704,6 +716,18 @@ mxml_write_node(mxml_node_t *node, /* I - Node to write */
switch (node->type)
{
case MXML_ELEMENT :
+ if (cb && (ch = (*cb)(node, MXML_SAVE_OPEN_TAG)) != 0)
+ {
+ if (putc(ch, fp) < 0)
+ return (-1);
+ else if (ch == '\n')
+ col = 0;
+ else if (ch == '\t')
+ col += 8;
+ else
+ col ++;
+ }
+
if ((n = fprintf(fp, "<%s", node->value.element.name)) < 0)
return (-1);
@@ -752,7 +776,7 @@ mxml_write_node(mxml_node_t *node, /* I - Node to write */
else
col ++;
- if ((col = mxml_write_node(node->child, fp, col)) < 0)
+ if ((col = mxml_write_node(node->child, fp, cb, col)) < 0)
return (-1);
if (node->value.element.name[0] != '?' &&
@@ -775,6 +799,18 @@ mxml_write_node(mxml_node_t *node, /* I - Node to write */
return (-1);
else
col += 2;
+
+ if (cb && (ch = (*cb)(node, MXML_SAVE_CLOSE_TAG)) != 0)
+ {
+ if (putc(ch, fp) < 0)
+ return (-1);
+ else if (ch == '\n')
+ col = 0;
+ else if (ch == '\t')
+ col += 8;
+ else
+ col ++;
+ }
break;
case MXML_INTEGER :
@@ -829,7 +865,7 @@ mxml_write_node(mxml_node_t *node, /* I - Node to write */
break;
case MXML_TEXT :
- if (node->value.text.whitespace)
+ if (node->value.text.whitespace && col > 0)
{
if (col > MXML_WRAP)
{
@@ -887,6 +923,11 @@ mxml_write_string(const char *s, /* I - String to write */
if (fputs(">", fp) < 0)
return (-1);
}
+ else if (*s == '\"')
+ {
+ if (fputs(""", fp) < 0)
+ return (-1);
+ }
else if (*s & 128)
{
/*
@@ -933,5 +974,5 @@ mxml_write_string(const char *s, /* I - String to write */
/*
- * End of "$Id: mxml-file.c,v 1.6 2003/06/04 16:30:40 mike Exp $".
+ * End of "$Id: mxml-file.c,v 1.7 2003/06/04 17:37:23 mike Exp $".
*/
diff --git a/mxml-node.c b/mxml-node.c
index dca8308..3e9849c 100644
--- a/mxml-node.c
+++ b/mxml-node.c
@@ -1,5 +1,5 @@
/*
- * "$Id: mxml-node.c,v 1.1 2003/06/03 19:46:30 mike Exp $"
+ * "$Id: mxml-node.c,v 1.2 2003/06/04 17:37:23 mike Exp $"
*
* Node support code for mini-XML, a small XML-like file parsing library.
*
@@ -17,12 +17,14 @@
*
* Contents:
*
+ * mxmlAdd() - Add a node to a tree.
* mxmlDelete() - Delete a node and all of its children.
* mxmlNewElement() - Create a new element node.
* mxmlNewInteger() - Create a new integer node.
* mxmlNewOpaque() - Create a new opaque string.
* mxmlNewReal() - Create a new real number node.
* mxmlNewText() - Create a new text fragment node.
+ * mxmlRemove() - Remove a node from its parent.
* mxml_new() - Create a new node.
*/
@@ -40,6 +42,98 @@
static mxml_node_t *mxml_new(mxml_node_t *parent, mxml_type_t type);
+/*
+ * 'mxmlAdd()' - Add a node to a tree.
+ */
+
+void
+mxmlAdd(mxml_node_t *parent, /* I - Parent node */
+ int where, /* I - Where to add */
+ mxml_node_t *child, /* I - Child node for where */
+ mxml_node_t *node) /* I - Node to add */
+{
+ if (!parent)
+ return;
+
+ if (node->parent)
+ mxmlRemove(node);
+
+ node->parent = parent;
+
+ switch (where)
+ {
+ case MXML_ADD_BEFORE :
+ if (!child || child == parent->child || child->parent != parent)
+ {
+ /*
+ * Insert as first node under parent...
+ */
+
+ node->next = parent->child;
+
+ if (parent->child)
+ parent->child->prev = node;
+ else
+ parent->last_child = node;
+
+ parent->child = node;
+ }
+ else
+ {
+ /*
+ * Insert node before this child...
+ */
+
+ node->next = child;
+ node->prev = child->prev;
+
+ if (child->prev)
+ child->prev->next = node;
+ else
+ parent->child = node;
+
+ child->prev = node;
+ }
+ break;
+
+ case MXML_ADD_AFTER :
+ if (!child || child == parent->last_child || child->parent != parent)
+ {
+ /*
+ * Insert as last node under parent...
+ */
+
+ node->parent = parent;
+ node->prev = parent->last_child;
+
+ if (parent->last_child)
+ parent->last_child->next = node;
+ else
+ parent->child = node;
+
+ parent->last_child = node;
+ }
+ else
+ {
+ /*
+ * Insert node after this child...
+ */
+
+ node->prev = child;
+ node->next = child->next;
+
+ if (child->next)
+ child->next->prev = node;
+ else
+ parent->last_child = node;
+
+ child->next = node;
+ }
+ break;
+ }
+}
+
+
/*
* 'mxmlDelete()' - Delete a node and all of its children.
*/
@@ -58,7 +152,13 @@ mxmlDelete(mxml_node_t *node) /* I - Node */
return;
/*
- * Delete children first...
+ * Remove the node from its parent, if any...
+ */
+
+ mxmlRemove(node);
+
+ /*
+ * Delete children...
*/
while (node->child)
@@ -103,23 +203,6 @@ mxmlDelete(mxml_node_t *node) /* I - Node */
break;
}
- /*
- * Remove from parent, if any...
- */
-
- if (node->parent)
- {
- if (node->prev)
- node->prev->next = node->next;
- else
- node->parent->child = node->next;
-
- if (node->next)
- node->next->prev = node->prev;
- else
- node->parent->last_child = node->prev;
- }
-
/*
* Free this node...
*/
@@ -277,6 +360,36 @@ mxmlNewText(mxml_node_t *parent, /* I - Parent node */
}
+/*
+ * 'mxmlRemove()' - Remove a node from its parent.
+ */
+
+void
+mxmlRemove(mxml_node_t *node) /* I - Node to remove */
+{
+ /*
+ * Range check input...
+ */
+
+ if (!node || !node->parent)
+ return;
+
+ /*
+ * Remove from parent...
+ */
+
+ if (node->prev)
+ node->prev->next = node->next;
+ else
+ node->parent->child = node->next;
+
+ if (node->next)
+ node->next->prev = node->prev;
+ else
+ node->parent->last_child = node->prev;
+}
+
+
/*
* 'mxml_new()' - Create a new node.
*/
@@ -306,17 +419,7 @@ mxml_new(mxml_node_t *parent, /* I - Parent node */
*/
if (parent)
- {
- node->parent = parent;
- node->prev = parent->last_child;
-
- if (parent->last_child)
- parent->last_child->next = node;
- else
- parent->child = node;
-
- parent->last_child = node;
- }
+ mxmlAdd(parent, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, node);
/*
* Return the new node...
@@ -327,5 +430,5 @@ mxml_new(mxml_node_t *parent, /* I - Parent node */
/*
- * End of "$Id: mxml-node.c,v 1.1 2003/06/03 19:46:30 mike Exp $".
+ * End of "$Id: mxml-node.c,v 1.2 2003/06/04 17:37:23 mike Exp $".
*/
diff --git a/mxml.h b/mxml.h
index d18c38a..8eef0fe 100644
--- a/mxml.h
+++ b/mxml.h
@@ -1,5 +1,5 @@
/*
- * "$Id: mxml.h,v 1.5 2003/06/04 16:30:40 mike Exp $"
+ * "$Id: mxml.h,v 1.6 2003/06/04 17:37:23 mike Exp $"
*
* Header file for mini-XML, a small XML-like file parsing library.
*
@@ -38,14 +38,21 @@
* Constants...
*/
-# define MXML_NO_CALLBACK (mxml_type_t (*)(mxml_node_t *))0
- /* Don't use a type callback */
+# define MXML_NO_CALLBACK 0 /* Don't use a type callback */
# define MXML_WRAP 72 /* Wrap XML output at this column position */
# define MXML_DESCEND 1 /* Descend when finding/walking */
# define MXML_NO_DESCEND 0 /* Don't descend when finding/walking */
# define MXML_DESCEND_FIRST -1 /* Descend for first find */
+# define MXML_SAVE_OPEN_TAG 0 /* Callback for open tag */
+# define MXML_SAVE_CLOSE_TAG 1 /* Callback for close tag */
+
+
+# define MXML_ADD_BEFORE 0 /* Add node before specified node */
+# define MXML_ADD_AFTER 1 /* Add node after specified node */
+# define MXML_ADD_TO_PARENT NULL /* Add node relative to parent */
+
/*
* Data types...
@@ -110,6 +117,8 @@ extern "C" {
* Prototypes...
*/
+extern void mxmlAdd(mxml_node_t *parent, int where,
+ mxml_node_t *child, mxml_node_t *node);
extern void mxmlDelete(mxml_node_t *node);
extern const char *mxmlElementGetAttr(mxml_node_t *node, const char *name);
extern void mxmlElementSetAttr(mxml_node_t *node, const char *name,
@@ -125,7 +134,9 @@ extern mxml_node_t *mxmlNewOpaque(mxml_node_t *parent, const char *opaque);
extern mxml_node_t *mxmlNewReal(mxml_node_t *parent, double real);
extern mxml_node_t *mxmlNewText(mxml_node_t *parent, int whitespace,
const char *string);
-extern int mxmlSaveFile(mxml_node_t *node, FILE *fp);
+extern void mxmlRemove(mxml_node_t *node);
+extern int mxmlSaveFile(mxml_node_t *node, FILE *fp,
+ int (*cb)(mxml_node_t *, int));
extern mxml_node_t *mxmlWalkNext(mxml_node_t *node, mxml_node_t *top,
int descend);
extern mxml_node_t *mxmlWalkPrev(mxml_node_t *node, mxml_node_t *top,
@@ -143,5 +154,5 @@ extern mxml_node_t *mxmlWalkPrev(mxml_node_t *node, mxml_node_t *top,
/*
- * End of "$Id: mxml.h,v 1.5 2003/06/04 16:30:40 mike Exp $".
+ * End of "$Id: mxml.h,v 1.6 2003/06/04 17:37:23 mike Exp $".
*/
diff --git a/mxmldoc.c b/mxmldoc.c
index bf7ece6..7651a5f 100644
--- a/mxmldoc.c
+++ b/mxmldoc.c
@@ -1,5 +1,5 @@
/*
- * "$Id: mxmldoc.c,v 1.2 2003/06/04 16:30:40 mike Exp $"
+ * "$Id: mxmldoc.c,v 1.3 2003/06/04 17:37:23 mike Exp $"
*
* Documentation generator using mini-XML, a small XML-like file parsing
* library.
@@ -102,9 +102,9 @@
* Local functions...
*/
-static void insert_node(mxml_node_t *tree, mxml_node_t *func);
static int scan_file(const char *filename, FILE *fp,
mxml_node_t *doc);
+static void sort_node(mxml_node_t *tree, mxml_node_t *func);
/*
@@ -193,7 +193,7 @@ main(int argc, /* I - Number of command-line args */
* Write over the existing XML file...
*/
- if (mxmlSaveFile(doc, fp))
+ if (mxmlSaveFile(doc, fp, MXML_NO_CALLBACK))
{
fprintf(stderr, "Unable to write the XML documentation file \"%s\": %s!\n",
argv[1], strerror(errno));
@@ -223,12 +223,24 @@ main(int argc, /* I - Number of command-line args */
/*
- * 'insert_node()' - Insert a node into a tree.
+ * 'scan_file()' - Scan a source file.
+ */
+
+static int /* O - 0 on success, -1 on error */
+scan_file(const char *filename, /* I - Filename */
+ FILE *fp, /* I - File to scan */
+ mxml_node_t *tree) /* I - Function tree */
+{
+}
+
+
+/*
+ * 'sort_node()' - Insert a node sorted into a tree.
*/
static void
-insert_node(mxml_node_t *tree, /* I - Tree to insert into */
- mxml_node_t *node) /* I - Node to add */
+sort_node(mxml_node_t *tree, /* I - Tree to sort into */
+ mxml_node_t *node) /* I - Node to add */
{
mxml_node_t *temp; /* Current node */
const char *tempname, /* Name of current node */
@@ -242,7 +254,7 @@ insert_node(mxml_node_t *tree, /* I - Tree to insert into */
nodename = mxmlElementGetAttr(node, "name");
/*
- * Delete an existing definition, if one exists...
+ * Delete any existing definition at this level, if one exists...
*/
if ((temp = mxmlFindElement(tree, tree, node->value.element.name,
@@ -250,7 +262,7 @@ insert_node(mxml_node_t *tree, /* I - Tree to insert into */
mxmlDelete(temp);
/*
- * Insert the node into the tree...
+ * Add the node into the tree at the proper place...
*/
for (temp = tree->child; temp; temp = temp->next)
@@ -262,53 +274,10 @@ insert_node(mxml_node_t *tree, /* I - Tree to insert into */
break;
}
- if (temp)
- {
- /*
- * Insert node before this temp...
- */
-
- node->next = temp;
- node->prev = temp->prev;
-
- if (temp->prev)
- temp->prev->next = node;
- else
- tree->child = node;
-
- temp->prev = node;
- }
- else
- {
- /*
- * Append node to the end...
- */
-
- node->prev = tree->last_child;
-
- if (tree->last_child)
- tree->last_child->next = node;
- else
- tree->last_child = node;
-
- if (!tree->child)
- tree->child = node;
- }
-}
-
-
-/*
- * 'scan_file()' - Scan a source file.
- */
-
-static int /* O - 0 on success, -1 on error */
-scan_file(const char *filename, /* I - Filename */
- FILE *fp, /* I - File to scan */
- mxml_node_t *tree) /* I - Function tree */
-{
+ mxmlAdd(tree, MXML_ADD_AFTER, temp, node);
}
/*
- * End of "$Id: mxmldoc.c,v 1.2 2003/06/04 16:30:40 mike Exp $".
+ * End of "$Id: mxmldoc.c,v 1.3 2003/06/04 17:37:23 mike Exp $".
*/
diff --git a/testmxml.c b/testmxml.c
index 02a6554..ef15702 100644
--- a/testmxml.c
+++ b/testmxml.c
@@ -1,5 +1,5 @@
/*
- * "$Id: testmxml.c,v 1.5 2003/06/04 16:30:40 mike Exp $"
+ * "$Id: testmxml.c,v 1.6 2003/06/04 17:37:23 mike Exp $"
*
* Test program for mini-XML, a small XML-like file parsing library.
*
@@ -17,8 +17,10 @@
*
* Contents:
*
- * main() - Main entry for test program.
- * type_cb() - XML data type callback for mxmlLoadFile()...
+ * main() - Main entry for test program.
+ * type_cb() - XML data type callback for mxmlLoadFile()...
+ * whitespace_cb() - Let the mxmlSaveFile() function know when to insert
+ * newlines and tabs...
*/
/*
@@ -33,6 +35,7 @@
*/
mxml_type_t type_cb(mxml_node_t *node);
+int whitespace_cb(mxml_node_t *node, int where);
/*
@@ -110,8 +113,7 @@ main(int argc, /* I - Number of command-line args */
* Print the XML tree...
*/
- mxmlSaveFile(tree, stdout);
- puts("");
+ mxmlSaveFile(tree, stdout, whitespace_cb);
/*
* Delete the tree and return...
@@ -142,8 +144,7 @@ type_cb(mxml_node_t *node) /* I - Element node */
if (!strcmp(type, "integer"))
return (MXML_INTEGER);
- else if (!strcmp(type, "opaque") ||
- !strcmp(type, "pre") || !strcmp(type, "PRE"))
+ else if (!strcmp(type, "opaque") || !strcmp(type, "pre"))
return (MXML_OPAQUE);
else if (!strcmp(type, "real"))
return (MXML_REAL);
@@ -153,5 +154,44 @@ type_cb(mxml_node_t *node) /* I - Element node */
/*
- * End of "$Id: testmxml.c,v 1.5 2003/06/04 16:30:40 mike Exp $".
+ * 'whitespace_cb()' - Let the mxmlSaveFile() function know when to insert
+ * newlines and tabs...
+ */
+
+int /* O - Whitespace char or 0 */
+whitespace_cb(mxml_node_t *node, /* I - Element node */
+ int where) /* I - Open or close tag? */
+{
+ const char *name; /* Name of element */
+
+ /*
+ * We can conditionally break to a new line before or after any element.
+ * These are just common HTML elements...
+ */
+
+ name = node->value.element.name;
+
+ if (!strcmp(name, "html") || !strcmp(name, "head") || !strcmp(name, "body") ||
+ !strcmp(name, "pre") || !strcmp(name, "p") ||
+ !strcmp(name, "h1") || !strcmp(name, "h2") || !strcmp(name, "h3") ||
+ !strcmp(name, "h4") || !strcmp(name, "h5") || !strcmp(name, "h6"))
+ return ('\n');
+ else if (!strcmp(name, "li"))
+ {
+ /*
+ * Put a tab before 's and a newline after 's...
+ */
+
+ if (where == MXML_SAVE_OPEN_TAG)
+ return ('\t');
+ else
+ return ('\n');
+ }
+ else
+ return (0);
+}
+
+
+/*
+ * End of "$Id: testmxml.c,v 1.6 2003/06/04 17:37:23 mike Exp $".
*/