Commit 04ce2615 authored by Michael R Sweet's avatar Michael R Sweet

Fix handling of quoted element and attribute names.

Update changelog.
parent 380fcfdf
README - 09/28/2003
README - 12/01/2003
-------------------
CHANGES IN Mini-XML 1.3
- The mxmlElementSetAttr() function now allows for NULL
attribute values.
- The load and save functions now properly handle quoted
element and attribute name strings properly, e.g. for
!DOCTYPE declarations.
CHANGES IN Mini-XML 1.2
- Added new "set" methods to set the value of a node.
......
README - 09/28/2003
README - 12/01/2003
-------------------
INTRODUCTION
This README file describes the Mini-XML library version 1.2.
This README file describes the Mini-XML library version 1.3.
Mini-XML is a small XML parsing library that you can use to
read XML and XML-like data files in your application without
......@@ -14,8 +14,8 @@ INTRODUCTION
Mini-XML provides the following functionality:
- Reading and writing of UTF-8 encoded XML files.
- Reading and writing of UTF-8 encoded XML strings.
- Reading and writing of UTF-8 encoded XML files and
strings.
- Data is stored in a linked-list tree structure,
preserving the XML data hierarchy.
- Supports arbitrary element names, attributes, and
......@@ -76,7 +76,7 @@ DOCUMENTATION
The documentation is currently a work in progress. Aside
from the information that follows, the "documentation.html"
page provides a handy reference and is automatically
generated using Mini-XML. You can also look at the
generated using Mini-XML. You can also look at the
"testmxml.c" and "mxmldoc.c" source files for examples of
using Mini-XML.
......
......@@ -16,11 +16,11 @@ href="../index.html">Back to Home Page</a>&nbsp;]</p>
<h1 class="title" align="center">Mini-XML Home Page</h1>
<p class="title" align="center">Current Release: v1.2, September 28, 2003<br/>
<p class="title" align="center">Current Release: v1.3, December 1, 2003<br/>
[&nbsp;<a
href="mxml-1.2.tar.gz">Download&nbsp;Source&nbsp;(.tar.gz&nbsp;77k)</a>
href="mxml-1.3.tar.gz">Download&nbsp;Source&nbsp;(.tar.gz&nbsp;77k)</a>
| <a
href="mxml-1.2-1.i386.rpm">Download&nbsp;Linux&nbsp;RPM&nbsp;(.i386.rpm&nbsp;67k)</a>
href="mxml-1.3-1.i386.rpm">Download&nbsp;Linux&nbsp;RPM&nbsp;(.i386.rpm&nbsp;67k)</a>
| <a href="CHANGES">Change&nbsp;Log</a> | <a
href="documentation.html">Documentation</a> | <a
href="http://freshmeat.net/projects/mxml">Rate/Make&nbsp;Comments</A>&nbsp;]</p>
......@@ -36,7 +36,8 @@ ANSI C compilers) and a "make" program.</p>
<p>Mini-XML provides the following functionality:</p>
<ul>
<li>Reading and writing of UTF-8 encoded XML files.</li>
<li>Reading and writing of UTF-8 encoded XML files and
strings.</li>
<li>Data is stored in a linked-list tree structure,
preserving the XML data hierarchy.</li>
<li>Supports arbitrary element names, attributes, and
......
/*
* "$Id: mxml-attr.c,v 1.4 2003/07/27 23:11:40 mike Exp $"
* "$Id: mxml-attr.c,v 1.5 2003/12/01 15:27:47 mike Exp $"
*
* Attribute support code for mini-XML, a small XML-like file parsing library.
*
......@@ -91,7 +91,7 @@ mxmlElementSetAttr(mxml_node_t *node, /* I - Element node */
* Range check input...
*/
if (!node || node->type != MXML_ELEMENT || !name || !value)
if (!node || node->type != MXML_ELEMENT || !name)
return;
/*
......@@ -109,7 +109,10 @@ mxmlElementSetAttr(mxml_node_t *node, /* I - Element node */
free(attr->value);
attr->value = strdup(value);
if (value)
attr->value = strdup(value);
else
attr->value = NULL;
return;
}
......@@ -135,9 +138,12 @@ mxmlElementSetAttr(mxml_node_t *node, /* I - Element node */
attr += node->value.element.num_attrs;
attr->name = strdup(name);
attr->value = strdup(value);
if (value)
attr->value = strdup(value);
else
attr->value = NULL;
if (!attr->name || !attr->value)
if (!attr->name || (!attr->value && value))
{
if (attr->name)
free(attr->name);
......@@ -156,5 +162,5 @@ mxmlElementSetAttr(mxml_node_t *node, /* I - Element node */
/*
* End of "$Id: mxml-attr.c,v 1.4 2003/07/27 23:11:40 mike Exp $".
* End of "$Id: mxml-attr.c,v 1.5 2003/12/01 15:27:47 mike Exp $".
*/
/*
* "$Id: mxml-file.c,v 1.21 2003/09/28 21:09:04 mike Exp $"
* "$Id: mxml-file.c,v 1.22 2003/12/01 15:27:47 mike Exp $"
*
* File loading code for mini-XML, a small XML-like file parsing library.
*
......@@ -27,6 +27,7 @@
* mxml_load_data() - Load data into an XML node tree.
* mxml_parse_element() - Parse an element for any attributes...
* mxml_string_getc() - Get a character from a string.
* mxml_write_name() - Write a name string.
* mxml_write_node() - Save an XML node to a file.
* mxml_write_string() - Write a string, escaping & and < as needed.
* mxml_write_ws() - Do whitespace callback...
......@@ -55,6 +56,8 @@ static int mxml_parse_element(mxml_node_t *node, void *p,
int (*getc_cb)(void *));
static int mxml_string_getc(void *p);
static int mxml_string_putc(int ch, void *p);
static int mxml_write_name(const char *s, void *p,
int (*putc_cb)(int, void *));
static int mxml_write_node(mxml_node_t *node, void *p,
int (*cb)(mxml_node_t *, int),
int col,
......@@ -896,15 +899,43 @@ mxml_parse_element(mxml_node_t *node, /* I - Element node */
name[0] = ch;
ptr = name + 1;
while ((ch = (*getc_cb)(p)) != EOF)
if (isspace(ch) || ch == '=' || ch == '/' || ch == '>' || ch == '?')
break;
else if (mxml_add_char(ch, &ptr, &name, &namesize))
if (ch == '\"' || ch == '\'')
{
/*
* Name is in quotes, so get a quoted string...
*/
quote = ch;
while ((ch = (*getc_cb)(p)) != EOF)
{
free(name);
free(value);
return (EOF);
if (mxml_add_char(ch, &ptr, &name, &namesize))
{
free(name);
free(value);
return (EOF);
}
if (ch == quote)
break;
}
}
else
{
/*
* Grab an normal, non-quoted name...
*/
while ((ch = (*getc_cb)(p)) != EOF)
if (isspace(ch) || ch == '=' || ch == '/' || ch == '>' || ch == '?')
break;
else if (mxml_add_char(ch, &ptr, &name, &namesize))
{
free(name);
free(value);
return (EOF);
}
}
*ptr = '\0';
......@@ -963,12 +994,24 @@ mxml_parse_element(mxml_node_t *node, /* I - Element node */
*ptr = '\0';
}
/*
* Set the attribute with the given string value...
*/
mxmlElementSetAttr(node, name, value);
}
else
value[0] = '\0';
{
/*
* Set the attribute with a NULL value...
*/
mxmlElementSetAttr(node, name, NULL);
}
/*
* Save last character in case we need it...
* Check the end character...
*/
if (ch == '/' || ch == '?')
......@@ -990,12 +1033,6 @@ mxml_parse_element(mxml_node_t *node, /* I - Element node */
}
else if (ch == '>')
break;
/*
* Set the attribute...
*/
mxmlElementSetAttr(node, name, value);
}
/*
......@@ -1054,6 +1091,166 @@ mxml_string_putc(int ch, /* I - Character to write */
}
/*
* 'mxml_write_name()' - Write a name string.
*/
static int /* O - 0 on success, -1 on failure */
mxml_write_name(const char *s, /* I - Name to write */
void *p, /* I - Write pointer */
int (*putc_cb)(int, void *))
/* I - Write callback */
{
char buf[255], /* Buffer */
*bufptr, /* Pointer into buffer */
quote; /* Quote character */
if (*s == '\"' || *s == '\'')
{
/*
* Write a quoted name string...
*/
if ((*putc_cb)(*s, p) < 0)
return (-1);
quote = *s++;
while (*s && *s != quote)
{
if (*s == '&')
{
if ((*putc_cb)('&', p) < 0)
return (-1);
if ((*putc_cb)('a', p) < 0)
return (-1);
if ((*putc_cb)('m', p) < 0)
return (-1);
if ((*putc_cb)('p', p) < 0)
return (-1);
if ((*putc_cb)(';', p) < 0)
return (-1);
}
else if (*s == '<')
{
if ((*putc_cb)('&', p) < 0)
return (-1);
if ((*putc_cb)('l', p) < 0)
return (-1);
if ((*putc_cb)('t', p) < 0)
return (-1);
if ((*putc_cb)(';', p) < 0)
return (-1);
}
else if (*s == '>')
{
if ((*putc_cb)('&', p) < 0)
return (-1);
if ((*putc_cb)('g', p) < 0)
return (-1);
if ((*putc_cb)('t', p) < 0)
return (-1);
if ((*putc_cb)(';', p) < 0)
return (-1);
}
else if (*s == '\"')
{
if ((*putc_cb)('&', p) < 0)
return (-1);
if ((*putc_cb)('q', p) < 0)
return (-1);
if ((*putc_cb)('u', p) < 0)
return (-1);
if ((*putc_cb)('o', p) < 0)
return (-1);
if ((*putc_cb)('t', p) < 0)
return (-1);
if ((*putc_cb)(';', p) < 0)
return (-1);
}
else if (*s & 128)
{
/*
* Convert UTF-8 to Unicode constant...
*/
int ch; /* Unicode character */
ch = *s & 255;
if ((ch & 0xe0) == 0xc0)
{
ch = ((ch & 0x1f) << 6) | (s[1] & 0x3f);
s ++;
}
else if ((ch & 0xf0) == 0xe0)
{
ch = ((((ch * 0x0f) << 6) | (s[1] & 0x3f)) << 6) | (s[2] & 0x3f);
s += 2;
}
if (ch == 0xa0)
{
/*
* Handle non-breaking space as-is...
*/
if ((*putc_cb)('&', p) < 0)
return (-1);
if ((*putc_cb)('n', p) < 0)
return (-1);
if ((*putc_cb)('b', p) < 0)
return (-1);
if ((*putc_cb)('s', p) < 0)
return (-1);
if ((*putc_cb)('p', p) < 0)
return (-1);
if ((*putc_cb)(';', p) < 0)
return (-1);
}
else
{
sprintf(buf, "&#x%x;", ch);
for (bufptr = buf; *bufptr; bufptr ++)
if ((*putc_cb)(*bufptr, p) < 0)
return (-1);
}
}
else if ((*putc_cb)(*s, p) < 0)
return (-1);
s ++;
}
/*
* Write the end quote...
*/
if ((*putc_cb)(quote, p) < 0)
return (-1);
}
else
{
/*
* Write a non-quoted name string...
*/
while (*s)
{
if ((*putc_cb)(*s, p) < 0)
return (-1);
s ++;
}
}
return (0);
}
/*
* 'mxml_write_node()' - Save an XML node to a file.
*/
......@@ -1066,7 +1263,8 @@ mxml_write_node(mxml_node_t *node, /* I - Node to write */
int col, /* I - Current column */
int (*putc_cb)(int, void *))
{
int i; /* Looping var */
int i, /* Looping var */
width; /* Width of attr + value */
mxml_attr_t *attr; /* Current attribute */
char s[255]; /* Temporary string */
......@@ -1084,7 +1282,7 @@ mxml_write_node(mxml_node_t *node, /* I - Node to write */
if ((*putc_cb)('<', p) < 0)
return (-1);
if (mxml_write_string(node->value.element.name, p, putc_cb) < 0)
if (mxml_write_name(node->value.element.name, p, putc_cb) < 0)
return (-1);
col += strlen(node->value.element.name) + 1;
......@@ -1093,7 +1291,12 @@ mxml_write_node(mxml_node_t *node, /* I - Node to write */
i > 0;
i --, attr ++)
{
if ((col + strlen(attr->name) + strlen(attr->value) + 3) > MXML_WRAP)
width = strlen(attr->name);
if (attr->value)
width += strlen(attr->value) + 3;
if ((col + width) > MXML_WRAP)
{
if ((*putc_cb)('\n', p) < 0)
return (-1);
......@@ -1108,18 +1311,22 @@ mxml_write_node(mxml_node_t *node, /* I - Node to write */
col ++;
}
if (mxml_write_string(attr->name, p, putc_cb) < 0)
return (-1);
if ((*putc_cb)('=', p) < 0)
return (-1);
if ((*putc_cb)('\"', p) < 0)
return (-1);
if (mxml_write_string(attr->value, p, putc_cb) < 0)
if (mxml_write_name(attr->name, p, putc_cb) < 0)
return (-1);
if ((*putc_cb)('\"', p) < 0)
return (-1);
col += strlen(attr->name) + strlen(attr->value) + 3;
if (attr->value)
{
if ((*putc_cb)('=', p) < 0)
return (-1);
if ((*putc_cb)('\"', p) < 0)
return (-1);
if (mxml_write_string(attr->value, p, putc_cb) < 0)
return (-1);
if ((*putc_cb)('\"', p) < 0)
return (-1);
}
col += width;
}
if (node->child)
......@@ -1440,5 +1647,5 @@ mxml_write_ws(mxml_node_t *node, /* I - Current node */
/*
* End of "$Id: mxml-file.c,v 1.21 2003/09/28 21:09:04 mike Exp $".
* End of "$Id: mxml-file.c,v 1.22 2003/12/01 15:27:47 mike Exp $".
*/
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment