Add docos for custom data handlers.

This commit is contained in:
Michael R Sweet 2004-11-13 16:51:21 +00:00
parent a2682a2ee2
commit 40adb027dd
5 changed files with 451 additions and 15 deletions

View File

@ -1,4 +1,4 @@
CHANGES - 10/27/2004
CHANGES - 11/13/2004
--------------------
CHANGES IN Mini-XML 2.1

4
README
View File

@ -1,10 +1,10 @@
README - 06/25/2004
README - 11/13/2004
-------------------
INTRODUCTION
This README file describes the Mini-XML library version 2.0.
This README file describes the Mini-XML library version 2.1.
Mini-XML is a small XML parsing library that you can use to
read XML and XML-like data files in your application without

View File

@ -186,6 +186,151 @@ call any of the save functions:</p>
</pre>
<h2>Custom Data Types</h2>
<p>Mini-XML supports custom data types via global load and save
callbacks. Only a single set of callbacks can be active at any
time, however your callbacks can store additional information in
order to support multiple custom data types as needed. The
<tt>MXML_CUSTOM</tt> node type identifies custom data nodes.</p>
<p>The load callback receives a pointer to the current data node
and a string of opaque character data from the XML source with
character entities converted to the corresponding UTF-8
characters. For example, if we wanted to support a custom
date/time type whose value is encoded as "yyyy-mm-ddThh:mm:ssZ"
(ISO format), the load callback would look like the
following:</p>
<pre>
typedef struct
{
unsigned year, /* Year */
month, /* Month */
day, /* Day */
hour, /* Hour */
minute, /* Minute */
second; /* Second */
time_t unix; /* UNIX time value */
} iso_date_time_t;
int /* I - 0 on success, -1 on error */
load_custom(mxml_node_t *node, /* I - Node */
const char *data) /* I - Value */
{
iso_date_time_t *dt; /* Date/time value */
struct tm tmdata; /* UNIX time data */
/*
* Allocate data structure...
*/
dt = calloc(1, sizeof(iso_date_time_t));
/*
* Try reading 6 unsigned integers from the data string...
*/
if (sscanf(data, "%u-%u-%uT%u:%u:%uZ",
&(dt->year), &(dt->month), &(dt->day),
&(dt->hour), &(dt->minute), &(dt->second)) != 6)
{
/*
* Unable to read numbers, free the data structure and return an
* error...
*/
free(dt);
return (-1);
}
/*
* Range check values...
*/
if (dt->month < 1 || dt->month > 12 ||
dt->day < 1 || dt->day > 31 ||
dt->hour < 0 || dt->hour > 23 ||
dt->minute < 0 || dt->minute > 59 ||
dt->second < 0 || dt->second > 59)
{
/*
* Date information is out of range...
*/
free(dt);
return (-1);
}
/*
* Convert ISO time to UNIX time in seconds...
*/
tmdata.tm_year = dt->year - 1900;
tmdata.tm_mon = dt->month - 1;
tmdata.tm_day = dt->day;
tmdata.tm_hour = dt->hour;
tmdata.tm_min = dt->minute;
tmdata.tm_sec = dt->second;
dt->unix = gmtime(&tmdata);
/*
* Assign custom node data and destroy function pointers...
*/
node->value.custom.data = dt;
node->value.custom.destroy = free;
/*
* Return with no errors...
*/
return (0);
}
</pre>
<p>The function itself can return 0 on success or -1 if it is
unable to decode the custom data or the data contains an error.
Custom data nodes contain a <tt>void</tt> pointer to the
allocated custom data for the node and a pointer to a destructor
function which will free the custom data when the node is
deleted.</p>
<p>The save callback receives the node pointer and returns an
allocated string containing the custom data value. The following
save callback could be used for our ISO date/time type:</p>
<pre>
char * /* I - Allocated string */
save_custom(mxml_node_t *node) /* I - Node */
{
char data[255]; /* Data string */
iso_date_time_t *dt; /* ISO date/time pointer */
dt = (iso_date_time_t *)node->custom.data;
snprintf(data, sizeof(data), "%04u-%02u-%02uT%02u:%02u:%02uZ",
dt->year, dt->month, dt->day, dt->hour,
dt->minute, dt->second);
return (strdup(data));
}
</pre>
<p>You register the callback functions using the <a
href='#mxmlSetCustomHandlers'><tt>mxmlSetCustomHandlers()</tt></a>
function:</p>
<pre>
mxmlSetCustomHandlers(load_custom, save_custom);
</pre>
<h2>Changing Node Values</h2>
<p>All of the examples so far have concentrated on creating and

View File

@ -1,6 +1,6 @@
<html>
<head>
<title>Mini-XML Programmers Manual, Version 2.0</title>
<title>Mini-XML Programmers Manual, Version 2.1</title>
<meta name='copyright' content='Copyright 2003-2004'/>
<meta name='author' content='Michael Sweet'/>
<meta name='keywords' content='XML, C, C++, library'/>
@ -9,7 +9,7 @@
<h1 align='right'><a name='INTRO'>Introduction</a></h1>
<p>This programmers manual describes Mini-XML version 2.0, a
<p>This programmers manual describes Mini-XML version 2.1, a
small XML parsing library that you can use to read and write XML
and XML-like data files in your application without requiring
large non-standard libraries. Mini-XML only requires an ANSI C

View File

@ -1,7 +1,7 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<HTML>
<HEAD>
<TITLE>Mini-XML Programmers Manual, Version 2.0</TITLE>
<TITLE>Mini-XML Programmers Manual, Version 2.1</TITLE>
<META NAME="author" CONTENT="Michael Sweet">
<META NAME="copyright" CONTENT="Copyright 2003-2004">
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=iso-iso-8859-1">
@ -19,8 +19,8 @@ PRE { font-family: monospace }
--></STYLE>
</HEAD>
<BODY>
<CENTER><A HREF="#CONTENTS"><IMG SRC="logo.png" BORDER="0" WIDTH="222" HEIGHT="181" ALT="Mini-XML Programmers Manual, Version 2.0"><BR>
<H1>Mini-XML Programmers Manual, Version 2.0</H1></A><BR>
<CENTER><A HREF="#CONTENTS"><IMG SRC="logo.png" BORDER="0" WIDTH="222" HEIGHT="181" ALT="Mini-XML Programmers Manual, Version 2.1"><BR>
<H1>Mini-XML Programmers Manual, Version 2.1</H1></A><BR>
Michael Sweet<BR>
Copyright 2003-2004<BR>
</CENTER>
@ -58,9 +58,10 @@ Copyright 2003-2004<BR>
<UL>
<LI><A HREF="#LOAD_CALLBACKS">Load Callbacks</A></LI>
<LI><A HREF="#SAVE_CALLBACKS">Save Callbacks</A></LI>
<LI><A HREF="#4_3">Changing Node Values</A></LI>
<LI><A HREF="#4_4">Formatted Text</A></LI>
<LI><A HREF="#4_5">Indexing</A></LI>
<LI><A HREF="#4_3">Custom Data Types</A></LI>
<LI><A HREF="#4_4">Changing Node Values</A></LI>
<LI><A HREF="#4_5">Formatted Text</A></LI>
<LI><A HREF="#4_6">Indexing</A></LI>
</UL>
<B><A HREF="#MXMLDOC">4 - Using the mxmldoc Utility</A></B>
<UL>
@ -120,6 +121,7 @@ Copyright 2003-2004<BR>
<LI><A HREF="#mxmlLoadFd">mxmlLoadFd()</A></LI>
<LI><A HREF="#mxmlLoadFile">mxmlLoadFile()</A></LI>
<LI><A HREF="#mxmlLoadString">mxmlLoadString()</A></LI>
<LI><A HREF="#mxmlNewCustom">mxmlNewCustom()</A></LI>
<LI><A HREF="#mxmlNewElement">mxmlNewElement()</A></LI>
<LI><A HREF="#mxmlNewInteger">mxmlNewInteger()</A></LI>
<LI><A HREF="#mxmlNewOpaque">mxmlNewOpaque()</A></LI>
@ -131,6 +133,8 @@ Copyright 2003-2004<BR>
<LI><A HREF="#mxmlSaveFd">mxmlSaveFd()</A></LI>
<LI><A HREF="#mxmlSaveFile">mxmlSaveFile()</A></LI>
<LI><A HREF="#mxmlSaveString">mxmlSaveString()</A></LI>
<LI><A HREF="#mxmlSetCustom">mxmlSetCustom()</A></LI>
<LI><A HREF="#mxmlSetCustomHandlers">mxmlSetCustomHandlers()</A></LI>
<LI><A HREF="#mxmlSetElement">mxmlSetElement()</A></LI>
<LI><A HREF="#mxmlSetErrorCallback">mxmlSetErrorCallback()</A></LI>
<LI><A HREF="#mxmlSetInteger">mxmlSetInteger()</A></LI>
@ -145,6 +149,7 @@ Copyright 2003-2004<BR>
<LI><A HREF="#_structures">Structures</A>
<UL>
<LI><A HREF="#mxml_attr_s">mxml_attr_s</A></LI>
<LI><A HREF="#mxml_custom_s">mxml_custom_s</A></LI>
<LI><A HREF="#mxml_fdbuf_s">mxml_fdbuf_s</A></LI>
<LI><A HREF="#mxml_index_s">mxml_index_s</A></LI>
<LI><A HREF="#mxml_node_s">mxml_node_s</A></LI>
@ -155,6 +160,7 @@ Copyright 2003-2004<BR>
<LI><A HREF="#_types">Types</A>
<UL>
<LI><A HREF="#mxml_attr_t">mxml_attr_t</A></LI>
<LI><A HREF="#mxml_custom_t">mxml_custom_t</A></LI>
<LI><A HREF="#mxml_element_t">mxml_element_t</A></LI>
<LI><A HREF="#mxml_fdbuf_t">mxml_fdbuf_t</A></LI>
<LI><A HREF="#mxml_index_t">mxml_index_t</A></LI>
@ -171,13 +177,15 @@ Copyright 2003-2004<BR>
</LI>
<LI><A HREF="#_variables">Variables</A>
<UL>
<LI><A HREF="#mxml_custom_load_cb">mxml_custom_load_cb</A></LI>
<LI><A HREF="#mxml_custom_save_cb">mxml_custom_save_cb</A></LI>
<LI><A HREF="#num_callbacks">num_callbacks</A></LI>
</UL>
</LI>
</UL>
<HR NOSHADE>
<H1 align="right"><A name="INTRO">Introduction</A></H1>
<P>This programmers manual describes Mini-XML version 2.0, a small XML
<P>This programmers manual describes Mini-XML version 2.1, a small XML
parsing library that you can use to read and write XML and XML-like
data files in your application without requiring large non-standard
libraries. Mini-XML only requires an ANSI C compatible compiler (GCC
@ -808,7 +816,139 @@ MXML_WS_BEFORE_CLOSE</TT>, or <TT>MXML_WS_AFTER_CLOSE</TT>. The callback
<A href="#mxmlSaveFile">mxmlSaveFile</A>(tree, fp, whitespace_cb);
fclose(fp);
</PRE>
<H2><A NAME="4_3">Changing Node Values</A></H2>
<H2><A NAME="4_3">Custom Data Types</A></H2>
<P>Mini-XML supports custom data types via global load and save
callbacks. Only a single set of callbacks can be active at any time,
however your callbacks can store additional information in order to
support multiple custom data types as needed. The <TT>MXML_CUSTOM</TT>
node type identifies custom data nodes.</P>
<P>The load callback receives a pointer to the current data node and a
string of opaque character data from the XML source with character
entities converted to the corresponding UTF-8 characters. For example,
if we wanted to support a custom date/time type whose value is encoded
as &quot;yyyy-mm-ddThh:mm:ssZ&quot; (ISO format), the load callback would look
like the following:</P>
<PRE>
typedef struct
{
unsigned year, /* Year */
month, /* Month */
day, /* Day */
hour, /* Hour */
minute, /* Minute */
second; /* Second */
time_t unix; /* UNIX time value */
} iso_date_time_t;
int /* I - 0 on success, -1 on error */
load_custom(mxml_node_t *node, /* I - Node */
const char *data) /* I - Value */
{
iso_date_time_t *dt; /* Date/time value */
struct tm tmdata; /* UNIX time data */
/*
* Allocate data structure...
*/
dt = calloc(1, sizeof(iso_date_time_t));
/*
* Try reading 6 unsigned integers from the data string...
*/
if (sscanf(data, &quot;%u-%u-%uT%u:%u:%uZ&quot;,
&amp;(dt-&gt;year), &amp;(dt-&gt;month), &amp;(dt-&gt;day),
&amp;(dt-&gt;hour), &amp;(dt-&gt;minute), &amp;(dt-&gt;second)) != 6)
{
/*
* Unable to read numbers, free the data structure and return an
* error...
*/
free(dt);
return (-1);
}
/*
* Range check values...
*/
if (dt-&gt;month &lt;1 || dt-&gt;month &gt; 12 ||
dt-&gt;day &lt;1 || dt-&gt;day &gt; 31 ||
dt-&gt;hour &lt;0 || dt-&gt;hour &gt; 23 ||
dt-&gt;minute &lt;0 || dt-&gt;minute &gt; 59 ||
dt-&gt;second &lt;0 || dt-&gt;second &gt; 59)
{
/*
* Date information is out of range...
*/
free(dt);
return (-1);
}
/*
* Convert ISO time to UNIX time in seconds...
*/
tmdata.tm_year = dt-&gt;year - 1900;
tmdata.tm_mon = dt-&gt;month - 1;
tmdata.tm_day = dt-&gt;day;
tmdata.tm_hour = dt-&gt;hour;
tmdata.tm_min = dt-&gt;minute;
tmdata.tm_sec = dt-&gt;second;
dt-&gt;unix = gmtime(&amp;tmdata);
/*
* Assign custom node data and destroy function pointers...
*/
node-&gt;value.custom.data = dt;
node-&gt;value.custom.destroy = free;
/*
* Return with no errors...
*/
return (0);
}
</PRE>
<P>The function itself can return 0 on success or -1 if it is unable to
decode the custom data or the data contains an error. Custom data nodes
contain a <TT>void</TT> pointer to the allocated custom data for the
node and a pointer to a destructor function which will free the custom
data when the node is deleted.</P>
<P>The save callback receives the node pointer and returns an allocated
string containing the custom data value. The following save callback
could be used for our ISO date/time type:</P>
<PRE>
char * /* I - Allocated string */
save_custom(mxml_node_t *node) /* I - Node */
{
char data[255]; /* Data string */
iso_date_time_t *dt; /* ISO date/time pointer */
dt = (iso_date_time_t *)node-&gt;custom.data;
snprintf(data, sizeof(data), &quot;%04u-%02u-%02uT%02u:%02u:%02uZ&quot;,
dt-&gt;year, dt-&gt;month, dt-&gt;day, dt-&gt;hour,
dt-&gt;minute, dt-&gt;second);
return (strdup(data));
}
</PRE>
<P>You register the callback functions using the <A href="#mxmlSetCustomHandlers">
<TT>mxmlSetCustomHandlers()</TT></A> function:</P>
<PRE>
mxmlSetCustomHandlers(load_custom, save_custom);
</PRE>
<H2><A NAME="4_4">Changing Node Values</A></H2>
<P>All of the examples so far have concentrated on creating and loading
new XML data nodes. Many applications, however, need to manipulate or
change the nodes during their operation, so Mini-XML provides functions
@ -825,7 +965,7 @@ mxmlSetInteger()</TT></A>, <A href="#mxmlSetOpaque"><TT>mxmlSetOpaque()</TT>
<A href="#mxmlSetText">mxmlSetText</A>(node, 1, &quot;new&quot;);
</PRE>
<H2><A NAME="4_4">Formatted Text</A></H2>
<H2><A NAME="4_5">Formatted Text</A></H2>
<P>The <A href="#mxmlNewTextf"><TT>mxmlNewTextf()</TT></A> and <A href="#mxmlSetTextf">
<TT>mxmlSetTextf()</TT></A> functions create and change text nodes,
respectively, using <TT>printf</TT>-style format strings and arguments.
@ -836,7 +976,7 @@ mxmlSetInteger()</TT></A>, <A href="#mxmlSetOpaque"><TT>mxmlSetOpaque()</TT>
node = <A href="#mxmlNewTextf">mxmlNewTextf</A>(node, 1, &quot;%s/%s&quot;,
path, filename);
</PRE>
<H2><A NAME="4_5">Indexing</A></H2>
<H2><A NAME="4_6">Indexing</A></H2>
<P>Mini-XML provides functions for managing indices of nodes. The
current implementation provides the same functionality as the <A href="#mxmlFindElement">
<TT>mxmlFindElement()</TT></A>. The advantage of using an index is that
@ -1647,6 +1787,12 @@ mxmldoc</TT> to generate correct documentation for the code. Single line
<H1 align="right"><A name="RELNOTES">B - Release Notes</A></H1>
<H2><A NAME="7_1">Changes in Mini-XML 2.1</A></H2>
<UL>
<LI>Added support for custom data nodes (STR #6)</LI>
<LI>Now treat UTF-8 sequences which are longer than necessary as an
error (STR #4)</LI>
<LI>Fixed entity number support (STR #8)</LI>
<LI>Fixed mxmlLoadString() bug with UTF-8 (STR #7)</LI>
<LI>Fixed entity lookup bug (STR #5)</LI>
<LI>Added mxmlLoadFd() and mxmlSaveFd() functions.</LI>
<LI>Fixed multi-word UTF-16 handling.</LI>
</UL>
@ -1815,6 +1961,7 @@ mxmldoc</TT> to generate correct documentation for the code. Single line
<THEAD></THEAD>
<TR bgcolor="#cccccc"><TH>Name</TH><TH>Description</TH></TR>
<TBODY></TBODY>
<TR><TD><TT>MXML_CUSTOM</TT></TD><TD>Custom data</TD></TR>
<TR><TD><TT>MXML_ELEMENT</TT></TD><TD>XML element with attributes</TD></TR>
<TR><TD><TT>MXML_INTEGER</TT></TD><TD>Integer value</TD></TR>
<TR><TD><TT>MXML_OPAQUE</TT></TD><TD>Opaque string</TD></TR>
@ -1844,6 +1991,7 @@ mxmldoc</TT> to generate correct documentation for the code. Single line
<LI><A href="#mxmlLoadFd"><TT>mxmlLoadFd()</TT></A></LI>
<LI><A href="#mxmlLoadFile"><TT>mxmlLoadFile()</TT></A></LI>
<LI><A href="#mxmlLoadString"><TT>mxmlLoadString()</TT></A></LI>
<LI><A href="#mxmlNewCustom"><TT>mxmlNewCustom()</TT></A></LI>
<LI><A href="#mxmlNewElement"><TT>mxmlNewElement()</TT></A></LI>
<LI><A href="#mxmlNewInteger"><TT>mxmlNewInteger()</TT></A></LI>
<LI><A href="#mxmlNewOpaque"><TT>mxmlNewOpaque()</TT></A></LI>
@ -1855,6 +2003,9 @@ mxmldoc</TT> to generate correct documentation for the code. Single line
<LI><A href="#mxmlSaveFd"><TT>mxmlSaveFd()</TT></A></LI>
<LI><A href="#mxmlSaveFile"><TT>mxmlSaveFile()</TT></A></LI>
<LI><A href="#mxmlSaveString"><TT>mxmlSaveString()</TT></A></LI>
<LI><A href="#mxmlSetCustom"><TT>mxmlSetCustom()</TT></A></LI>
<LI><A href="#mxmlSetCustomHandlers"><TT>mxmlSetCustomHandlers()</TT></A>
</LI>
<LI><A href="#mxmlSetElement"><TT>mxmlSetElement()</TT></A></LI>
<LI><A href="#mxmlSetErrorCallback"><TT>mxmlSetErrorCallback()</TT></A></LI>
<LI><A href="#mxmlSetInteger"><TT>mxmlSetInteger()</TT></A></LI>
@ -2347,6 +2498,37 @@ mxmlLoadString(
<H4>Returns</H4>
<P>First node or NULL if the string has errors.</P>
<!-- NEW PAGE -->
<H3><A name="mxmlNewCustom">mxmlNewCustom()</A></H3>
<HR noshade/>
<H4>Description</H4>
<P>Create a new custom data node. The new custom node is added to the
end of the specified parent's child list. The constant MXML_NO_PARENT
can be used to specify that the new element node has no parent. NULL
can be passed when the data in the node is not dynamically allocated or
is separately managed.</P>
<H4>Syntax</H4>
<PRE>
<A href="#mxml_node_t">mxml_node_t</A> *
mxmlNewCustom(
<A href="#mxml_node_t">mxml_node_t</A> * parent,
void * data,
void (*destroy)(void *));
</PRE>
<H4>Arguments</H4>
<P class="table"></P>
<TABLE align="center" border="1" cellpadding="5" cellspacing="0" width="80%">
<THEAD></THEAD>
<TR bgcolor="#cccccc"><TH>Name</TH><TH>Description</TH></TR>
<TBODY></TBODY>
<TR><TD><TT>parent</TT></TD><TD>Parent node or MXML_NO_PARENT</TD></TR>
<TR><TD><TT>data</TT></TD><TD>Pointer to data</TD></TR>
<TR><TD><TT>(*destroy)(void *)</TT></TD><TD>Function to destroy data</TD>
</TR>
</TABLE>
<H4>Returns</H4>
<P>New node</P>
<!-- NEW PAGE -->
<H3><A name="mxmlNewElement">mxmlNewElement()</A></H3>
<HR noshade/>
@ -2673,6 +2855,60 @@ mxmlSaveString(
<H4>Returns</H4>
<P>Size of string</P>
<!-- NEW PAGE -->
<H3><A name="mxmlSetCustom">mxmlSetCustom()</A></H3>
<HR noshade/>
<H4>Description</H4>
<P>Set the data and destructor of a custom data node. The node is not
changed if it is not a custom node.</P>
<H4>Syntax</H4>
<PRE>
int
mxmlSetCustom(
<A href="#mxml_node_t">mxml_node_t</A> * node,
void * data,
void (*destroy)(void *));
</PRE>
<H4>Arguments</H4>
<P class="table"></P>
<TABLE align="center" border="1" cellpadding="5" cellspacing="0" width="80%">
<THEAD></THEAD>
<TR bgcolor="#cccccc"><TH>Name</TH><TH>Description</TH></TR>
<TBODY></TBODY>
<TR><TD><TT>node</TT></TD><TD>Node to set</TD></TR>
<TR><TD><TT>data</TT></TD><TD>New data pointer</TD></TR>
<TR><TD><TT>(*destroy)(void *)</TT></TD><TD>New destructor function</TD></TR>
</TABLE>
<H4>Returns</H4>
<P>0 on success, -1 on failure</P>
<!-- NEW PAGE -->
<H3><A name="mxmlSetCustomHandlers">mxmlSetCustomHandlers()</A></H3>
<HR noshade/>
<H4>Description</H4>
<P>Set the handling functions for custom data. The load function accepts
a node pointer and a data string and must return 0 on success and
non-zero on error. The save function accepts a node pointer and must
return a malloc'd string on success and NULL on error.</P>
<H4>Syntax</H4>
<PRE>
void
mxmlSetCustomHandlers(
mxml_custom_load_cb_t load,
mxml_custom_save_cb_t save);
</PRE>
<H4>Arguments</H4>
<P class="table"></P>
<TABLE align="center" border="1" cellpadding="5" cellspacing="0" width="80%">
<THEAD></THEAD>
<TR bgcolor="#cccccc"><TH>Name</TH><TH>Description</TH></TR>
<TBODY></TBODY>
<TR><TD><TT>load</TT></TD><TD>Load function</TD></TR>
<TR><TD><TT>save</TT></TD><TD>Save function</TD></TR>
</TABLE>
<H4>Returns</H4>
<P>Nothing.</P>
<!-- NEW PAGE -->
<H3><A name="mxmlSetElement">mxmlSetElement()</A></H3>
<HR noshade/>
@ -2917,6 +3153,7 @@ mxmlWalkPrev(
<H2><A name="_structures">Structures</A></H2>
<UL>
<LI><A href="#mxml_attr_s"><TT>mxml_attr_s</TT></A></LI>
<LI><A href="#mxml_custom_s"><TT>mxml_custom_s</TT></A></LI>
<LI><A href="#mxml_fdbuf_s"><TT>mxml_fdbuf_s</TT></A></LI>
<LI><A href="#mxml_index_s"><TT>mxml_index_s</TT></A></LI>
<LI><A href="#mxml_node_s"><TT>mxml_node_s</TT></A></LI>
@ -2947,6 +3184,27 @@ struct mxml_attr_s
<TR><TD><TT>value</TT></TD><TD>Attribute value</TD></TR>
</TABLE>
<!-- NEW PAGE -->
<H3><A name="mxml_custom_s">mxml_custom_s</A></H3>
<HR noshade/>
<H4>Description</H4>
<P>An XML custom value.</P>
<H4>Definition</H4>
<PRE>
struct mxml_custom_s
{
void * data;
};
</PRE>
<H4>Members</H4>
<P class="table"></P>
<TABLE align="center" border="1" cellpadding="5" cellspacing="0" width="80%">
<THEAD></THEAD>
<TR bgcolor="#cccccc"><TH>Name</TH><TH>Description</TH></TR>
<TBODY></TBODY>
<TR><TD><TT>data</TT></TD><TD>Pointer to (allocated) custom data</TD></TR>
</TABLE>
<!-- NEW PAGE -->
<H3><A name="mxml_fdbuf_s">mxml_fdbuf_s</A></H3>
<HR noshade/>
@ -3086,6 +3344,7 @@ struct mxml_value_s
<H2><A name="_types">Types</A></H2>
<UL>
<LI><A href="#mxml_attr_t"><TT>mxml_attr_t</TT></A></LI>
<LI><A href="#mxml_custom_t"><TT>mxml_custom_t</TT></A></LI>
<LI><A href="#mxml_element_t"><TT>mxml_element_t</TT></A></LI>
<LI><A href="#mxml_fdbuf_t"><TT>mxml_fdbuf_t</TT></A></LI>
<LI><A href="#mxml_index_t"><TT>mxml_index_t</TT></A></LI>
@ -3105,6 +3364,16 @@ struct mxml_value_s
typedef struct <A href="#mxml_attr_s">mxml_attr_s</A> mxml_attr_t;
</PRE>
<!-- NEW PAGE -->
<H3><A name="mxml_custom_t">mxml_custom_t</A></H3>
<HR noshade/>
<H4>Description</H4>
<P>An XML custom value.</P>
<H4>Definition</H4>
<PRE>
typedef struct <A href="#mxml_custom_s">mxml_custom_s</A> mxml_custom_t;
</PRE>
<!-- NEW PAGE -->
<H3><A name="mxml_element_t">mxml_element_t</A></H3>
<HR noshade/>
@ -3190,6 +3459,7 @@ typedef union <A href="#mxml_value_u">mxml_value_u</A> mxml_value_t;
<PRE>
union mxml_value_u
{
<A href="#mxml_custom_t">mxml_custom_t</A> custom;
<A href="#mxml_element_t">mxml_element_t</A> element;
int integer;
char * opaque;
@ -3203,6 +3473,7 @@ union mxml_value_u
<THEAD></THEAD>
<TR bgcolor="#cccccc"><TH>Name</TH><TH>Description</TH></TR>
<TBODY></TBODY>
<TR><TD><TT>custom</TT></TD><TD>Custom data</TD></TR>
<TR><TD><TT>element</TT></TD><TD>Element</TD></TR>
<TR><TD><TT>integer</TT></TD><TD>Integer number</TD></TR>
<TR><TD><TT>opaque</TT></TD><TD>Opaque string</TD></TR>
@ -3213,9 +3484,29 @@ union mxml_value_u
<!-- NEW PAGE -->
<H2><A name="_variables">Variables</A></H2>
<UL>
<LI><A href="#mxml_custom_load_cb"><TT>mxml_custom_load_cb</TT></A></LI>
<LI><A href="#mxml_custom_save_cb"><TT>mxml_custom_save_cb</TT></A></LI>
<LI><A href="#num_callbacks"><TT>num_callbacks</TT></A></LI>
</UL>
<!-- NEW PAGE -->
<H3><A name="mxml_custom_load_cb">mxml_custom_load_cb</A></H3>
<HR noshade/>
<H4>Definition</H4>
<PRE>
static mxml_custom_load_cb_t mxml_custom_load_cb = NULL;
</PRE>
<!-- NEW PAGE -->
<H3><A name="mxml_custom_save_cb">mxml_custom_save_cb</A></H3>
<HR noshade/>
<H4>Description</H4>
<P>Local functions...</P>
<H4>Definition</H4>
<PRE>
static mxml_custom_save_cb_t mxml_custom_save_cb = NULL;
</PRE>
<!-- NEW PAGE -->
<H3><A name="num_callbacks">num_callbacks</A></H3>
<HR noshade/>