mirror of
https://github.com/michaelrsweet/mxml.git
synced 2025-02-19 17:05:30 +00:00
Index and entity callback support.
This commit is contained in:
parent
40db9196f3
commit
46085f9327
8
CHANGES
8
CHANGES
@ -1,9 +1,15 @@
|
||||
README - 05/02/2004
|
||||
README - 05/16/2004
|
||||
-------------------
|
||||
|
||||
CHANGES IN Mini-XML 2.0
|
||||
|
||||
- New programmers manual.
|
||||
- Added index functions to build a searchable index of
|
||||
XML nodes.
|
||||
- Added character entity callback interface to support
|
||||
additional character entities beyond those defined in
|
||||
the XHTML specification.
|
||||
- Added support for XHTML character entities.
|
||||
- The mxmldoc utility now produces XML output which
|
||||
conforms to an updated XML schema, described in the file
|
||||
"doc/mxmldoc.xsd".
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# "$Id: Makefile.in,v 1.20 2004/05/02 22:02:36 mike Exp $"
|
||||
# "$Id: Makefile.in,v 1.21 2004/05/16 05:25:38 mike Exp $"
|
||||
#
|
||||
# Makefile for Mini-XML, a small XML-like file parsing library.
|
||||
#
|
||||
@ -76,8 +76,8 @@ MAN3EXT = @MAN3EXT@
|
||||
|
||||
DOCFILES = doc/mxml.html doc/mxml.pdf doc/mxmldoc.xsd \
|
||||
README COPYING CHANGES
|
||||
PUBLIBOBJS = mxml-attr.o mxml-entity.o mxml-file.o mxml-node.o \
|
||||
mxml-search.o mxml-set.o
|
||||
PUBLIBOBJS = mxml-attr.o mxml-entity.o mxml-file.o mxml-index.o \
|
||||
mxml-node.o mxml-search.o mxml-set.o
|
||||
LIBOBJS = $(PUBLIBOBJS) mxml-private.o mxml-string.o
|
||||
OBJS = mxmldoc.o testmxml.o $(LIBOBJS)
|
||||
TARGETS = libmxml.a mxmldoc doc/mxml.$(CAT3EXT) \
|
||||
@ -257,5 +257,5 @@ $(OBJS): Makefile config.h
|
||||
|
||||
|
||||
#
|
||||
# End of "$Id: Makefile.in,v 1.20 2004/05/02 22:02:36 mike Exp $".
|
||||
# End of "$Id: Makefile.in,v 1.21 2004/05/16 05:25:38 mike Exp $".
|
||||
#
|
||||
|
11
TODO
11
TODO
@ -1,4 +1,4 @@
|
||||
TODO - 05/02/2004
|
||||
TODO - 05/16/2004
|
||||
-----------------
|
||||
|
||||
- UTF-16 support.
|
||||
@ -9,12 +9,6 @@ TODO - 05/02/2004
|
||||
-- Use HTMLDOC to generate
|
||||
-- Provide more tutorials
|
||||
-- Release notes
|
||||
- Add indexing support.
|
||||
-- Build static index of nodes based on element and/or attribute
|
||||
(i.e. index elements, index attributes, or index attributes of
|
||||
a specific element)
|
||||
-- Provide functions to create, destroy, find first, and find next
|
||||
-- Provide additional index for first character?
|
||||
- Add access methods and make node structure opaque.
|
||||
-- To allow for C++ migration
|
||||
-- To make future binary compatibility easier
|
||||
@ -24,6 +18,3 @@ TODO - 05/02/2004
|
||||
-- Make this the core implementation which the C API accesses?
|
||||
-- Class would allow for subclassing, is that necessary?
|
||||
- Binary XML support???
|
||||
- Character entity support
|
||||
-- Add support for a callback which returns a Unicode
|
||||
char from an entity name.
|
||||
|
@ -17,6 +17,7 @@
|
||||
<li><a href='#_structures'>Structures</a></li>
|
||||
<li><a href='#_types'>Types</a></li>
|
||||
<li><a href='#_unions'>Unions</a></li>
|
||||
<li><a href='#_variables'>Variables</a></li>
|
||||
</ul>
|
||||
<!-- NEW PAGE -->
|
||||
<h2><a name='_enumerations'>Enumerations</a></h2>
|
||||
@ -45,9 +46,16 @@
|
||||
<li><a href='#mxmlDelete'><tt>mxmlDelete()</tt></a></li>
|
||||
<li><a href='#mxmlElementGetAttr'><tt>mxmlElementGetAttr()</tt></a></li>
|
||||
<li><a href='#mxmlElementSetAttr'><tt>mxmlElementSetAttr()</tt></a></li>
|
||||
<li><a href='#mxmlEntityAddCallback'><tt>mxmlEntityAddCallback()</tt></a></li>
|
||||
<li><a href='#mxmlEntityGetName'><tt>mxmlEntityGetName()</tt></a></li>
|
||||
<li><a href='#mxmlEntityGetValue'><tt>mxmlEntityGetValue()</tt></a></li>
|
||||
<li><a href='#mxmlEntityRemoveCallback'><tt>mxmlEntityRemoveCallback()</tt></a></li>
|
||||
<li><a href='#mxmlFindElement'><tt>mxmlFindElement()</tt></a></li>
|
||||
<li><a href='#mxmlIndexDelete'><tt>mxmlIndexDelete()</tt></a></li>
|
||||
<li><a href='#mxmlIndexEnum'><tt>mxmlIndexEnum()</tt></a></li>
|
||||
<li><a href='#mxmlIndexFind'><tt>mxmlIndexFind()</tt></a></li>
|
||||
<li><a href='#mxmlIndexNew'><tt>mxmlIndexNew()</tt></a></li>
|
||||
<li><a href='#mxmlIndexReset'><tt>mxmlIndexReset()</tt></a></li>
|
||||
<li><a href='#mxmlLoadFile'><tt>mxmlLoadFile()</tt></a></li>
|
||||
<li><a href='#mxmlLoadString'><tt>mxmlLoadString()</tt></a></li>
|
||||
<li><a href='#mxmlNewElement'><tt>mxmlNewElement()</tt></a></li>
|
||||
@ -177,6 +185,25 @@ mxmlElementSetAttr(
|
||||
<h4>Returns</h4>
|
||||
<p>Nothing.</p>
|
||||
<!-- NEW PAGE -->
|
||||
<h3><a name='mxmlEntityAddCallback'>mxmlEntityAddCallback()</a></h3>
|
||||
<hr noshade/>
|
||||
<h4>Description</h4>
|
||||
<p>Add a callback to convert entities to Unicode.</p>
|
||||
<h4>Syntax</h4>
|
||||
<pre>
|
||||
void
|
||||
mxmlEntityAddCallback(
|
||||
int (*cb)(const char *name));
|
||||
</pre>
|
||||
<h4>Arguments</h4>
|
||||
<p class='table'><table align='center' border='1' width='80%' cellpadding='5' cellspacing='0' width='80%'>
|
||||
<thead><tr bgcolor='#cccccc'><th>Name</th><th>Description</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><tt>(*cb)(const char *name)</tt></td><td>Callback function to add</td></tr>
|
||||
</tbody></table></p>
|
||||
<h4>Returns</h4>
|
||||
<p>Nothing.</p>
|
||||
<!-- NEW PAGE -->
|
||||
<h3><a name='mxmlEntityGetName'>mxmlEntityGetName()</a></h3>
|
||||
<hr noshade/>
|
||||
<h4>Description</h4>
|
||||
@ -220,6 +247,25 @@ mxmlEntityGetValue(
|
||||
<h4>Returns</h4>
|
||||
<p>Character value or -1 on error</p>
|
||||
<!-- NEW PAGE -->
|
||||
<h3><a name='mxmlEntityRemoveCallback'>mxmlEntityRemoveCallback()</a></h3>
|
||||
<hr noshade/>
|
||||
<h4>Description</h4>
|
||||
<p>Remove a callback.</p>
|
||||
<h4>Syntax</h4>
|
||||
<pre>
|
||||
void
|
||||
mxmlEntityRemoveCallback(
|
||||
int (*cb)(const char *name));
|
||||
</pre>
|
||||
<h4>Arguments</h4>
|
||||
<p class='table'><table align='center' border='1' width='80%' cellpadding='5' cellspacing='0' width='80%'>
|
||||
<thead><tr bgcolor='#cccccc'><th>Name</th><th>Description</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><tt>(*cb)(const char *name)</tt></td><td>Callback function to remove</td></tr>
|
||||
</tbody></table></p>
|
||||
<h4>Returns</h4>
|
||||
<p>Nothing.</p>
|
||||
<!-- NEW PAGE -->
|
||||
<h3><a name='mxmlFindElement'>mxmlFindElement()</a></h3>
|
||||
<hr noshade/>
|
||||
<h4>Description</h4>
|
||||
@ -258,6 +304,109 @@ mxmlFindElement(
|
||||
<h4>Returns</h4>
|
||||
<p>Element node or NULL</p>
|
||||
<!-- NEW PAGE -->
|
||||
<h3><a name='mxmlIndexDelete'>mxmlIndexDelete()</a></h3>
|
||||
<hr noshade/>
|
||||
<h4>Description</h4>
|
||||
<p>Sort attribute...</p>
|
||||
<h4>Syntax</h4>
|
||||
<pre>
|
||||
void
|
||||
mxmlIndexDelete(
|
||||
<a href='#mxml_index_t'>mxml_index_t</a> * ind);
|
||||
</pre>
|
||||
<h4>Arguments</h4>
|
||||
<p class='table'><table align='center' border='1' width='80%' cellpadding='5' cellspacing='0' width='80%'>
|
||||
<thead><tr bgcolor='#cccccc'><th>Name</th><th>Description</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><tt>ind</tt></td><td>Index to delete</td></tr>
|
||||
</tbody></table></p>
|
||||
<h4>Returns</h4>
|
||||
<p>Nothing.</p>
|
||||
<!-- NEW PAGE -->
|
||||
<h3><a name='mxmlIndexEnum'>mxmlIndexEnum()</a></h3>
|
||||
<hr noshade/>
|
||||
<h4>Description</h4>
|
||||
<p>Return the next node in the index.</p>
|
||||
<h4>Syntax</h4>
|
||||
<pre>
|
||||
<a href='#mxml_node_t'>mxml_node_t</a> *
|
||||
mxmlIndexEnum(
|
||||
<a href='#mxml_index_t'>mxml_index_t</a> * ind);
|
||||
</pre>
|
||||
<h4>Arguments</h4>
|
||||
<p class='table'><table align='center' border='1' width='80%' cellpadding='5' cellspacing='0' width='80%'>
|
||||
<thead><tr bgcolor='#cccccc'><th>Name</th><th>Description</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><tt>ind</tt></td><td>Index to enumerate</td></tr>
|
||||
</tbody></table></p>
|
||||
<h4>Returns</h4>
|
||||
<p>Next node or NULL if there is none</p>
|
||||
<!-- NEW PAGE -->
|
||||
<h3><a name='mxmlIndexFind'>mxmlIndexFind()</a></h3>
|
||||
<hr noshade/>
|
||||
<h4>Description</h4>
|
||||
<p>Find the next matching node.</p>
|
||||
<h4>Syntax</h4>
|
||||
<pre>
|
||||
<a href='#mxml_node_t'>mxml_node_t</a> *
|
||||
mxmlIndexFind(
|
||||
<a href='#mxml_index_t'>mxml_index_t</a> * ind,
|
||||
const char * element,
|
||||
const char * value);
|
||||
</pre>
|
||||
<h4>Arguments</h4>
|
||||
<p class='table'><table align='center' border='1' width='80%' cellpadding='5' cellspacing='0' width='80%'>
|
||||
<thead><tr bgcolor='#cccccc'><th>Name</th><th>Description</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><tt>ind</tt></td><td>Index to search</td></tr>
|
||||
<tr><td><tt>element</tt></td><td>Element name to find, if any</td></tr>
|
||||
<tr><td><tt>value</tt></td><td>Attribute value, if any</td></tr>
|
||||
</tbody></table></p>
|
||||
<h4>Returns</h4>
|
||||
<p>Node or NULL if none found</p>
|
||||
<!-- NEW PAGE -->
|
||||
<h3><a name='mxmlIndexNew'>mxmlIndexNew()</a></h3>
|
||||
<hr noshade/>
|
||||
<h4>Description</h4>
|
||||
<p>Create a new index.</p>
|
||||
<h4>Syntax</h4>
|
||||
<pre>
|
||||
<a href='#mxml_index_t'>mxml_index_t</a> *
|
||||
mxmlIndexNew(
|
||||
<a href='#mxml_node_t'>mxml_node_t</a> * node,
|
||||
const char * element,
|
||||
const char * attr);
|
||||
</pre>
|
||||
<h4>Arguments</h4>
|
||||
<p class='table'><table align='center' border='1' width='80%' cellpadding='5' cellspacing='0' width='80%'>
|
||||
<thead><tr bgcolor='#cccccc'><th>Name</th><th>Description</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><tt>node</tt></td><td>XML node tree</td></tr>
|
||||
<tr><td><tt>element</tt></td><td>Element to index or NULL for all</td></tr>
|
||||
<tr><td><tt>attr</tt></td><td>Attribute to index or NULL for none</td></tr>
|
||||
</tbody></table></p>
|
||||
<h4>Returns</h4>
|
||||
<p>New index</p>
|
||||
<!-- NEW PAGE -->
|
||||
<h3><a name='mxmlIndexReset'>mxmlIndexReset()</a></h3>
|
||||
<hr noshade/>
|
||||
<h4>Description</h4>
|
||||
<p>Return the first node in the index.</p>
|
||||
<h4>Syntax</h4>
|
||||
<pre>
|
||||
<a href='#mxml_node_t'>mxml_node_t</a> *
|
||||
mxmlIndexReset(
|
||||
<a href='#mxml_index_t'>mxml_index_t</a> * ind);
|
||||
</pre>
|
||||
<h4>Arguments</h4>
|
||||
<p class='table'><table align='center' border='1' width='80%' cellpadding='5' cellspacing='0' width='80%'>
|
||||
<thead><tr bgcolor='#cccccc'><th>Name</th><th>Description</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><tt>ind</tt></td><td>Index to reset</td></tr>
|
||||
</tbody></table></p>
|
||||
<h4>Returns</h4>
|
||||
<p>First node or NULL if there is none</p>
|
||||
<!-- NEW PAGE -->
|
||||
<h3><a name='mxmlLoadFile'>mxmlLoadFile()</a></h3>
|
||||
<hr noshade/>
|
||||
<h4>Description</h4>
|
||||
@ -814,6 +963,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_index_s'><tt>mxml_index_s</tt></a></li>
|
||||
<li><a href='#mxml_node_s'><tt>mxml_node_s</tt></a></li>
|
||||
<li><a href='#mxml_text_s'><tt>mxml_text_s</tt></a></li>
|
||||
<li><a href='#mxml_value_s'><tt>mxml_value_s</tt></a></li>
|
||||
@ -839,6 +989,32 @@ struct mxml_attr_s
|
||||
<tr><td><tt>value</tt></td><td>Attribute value</td></tr>
|
||||
</tbody></table></p>
|
||||
<!-- NEW PAGE -->
|
||||
<h3><a name='mxml_index_s'>mxml_index_s</a></h3>
|
||||
<hr noshade/>
|
||||
<h4>Description</h4>
|
||||
<p>An XML node index.</p>
|
||||
<h4>Definition</h4>
|
||||
<pre>
|
||||
struct mxml_index_s
|
||||
{
|
||||
int alloc_nodes;
|
||||
char * attr;
|
||||
int cur_node;
|
||||
<a href='#mxml_node_t'>mxml_node_t</a> ** nodes;
|
||||
int num_nodes;
|
||||
};
|
||||
</pre>
|
||||
<h4>Members</h4>
|
||||
<p class='table'><table align='center' border='1' width='80%' cellpadding='5' cellspacing='0' width='80%'>
|
||||
<thead><tr bgcolor='#cccccc'><th>Name</th><th>Description</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><tt>alloc_nodes</tt></td><td>Allocated nodes in index</td></tr>
|
||||
<tr><td><tt>attr</tt></td><td>Attribute used for indexing or NULL</td></tr>
|
||||
<tr><td><tt>cur_node</tt></td><td>Current node</td></tr>
|
||||
<tr><td><tt>nodes</tt></td><td>Node array</td></tr>
|
||||
<tr><td><tt>num_nodes</tt></td><td>Number of nodes in index</td></tr>
|
||||
</tbody></table></p>
|
||||
<!-- NEW PAGE -->
|
||||
<h3><a name='mxml_node_s'>mxml_node_s</a></h3>
|
||||
<hr noshade/>
|
||||
<h4>Description</h4>
|
||||
@ -915,6 +1091,7 @@ struct mxml_value_s
|
||||
<ul>
|
||||
<li><a href='#mxml_attr_t'><tt>mxml_attr_t</tt></a></li>
|
||||
<li><a href='#mxml_element_t'><tt>mxml_element_t</tt></a></li>
|
||||
<li><a href='#mxml_index_t'><tt>mxml_index_t</tt></a></li>
|
||||
<li><a href='#mxml_node_t'><tt>mxml_node_t</tt></a></li>
|
||||
<li><a href='#mxml_text_t'><tt>mxml_text_t</tt></a></li>
|
||||
<li><a href='#mxml_type_t'><tt>mxml_type_t</tt></a></li>
|
||||
@ -939,6 +1116,15 @@ typedef struct <a href='#mxml_attr_s'>mxml_attr_s</a> mxml_attr_t;
|
||||
typedef struct <a href='#mxml_value_s'>mxml_value_s</a> mxml_element_t;
|
||||
</pre>
|
||||
<!-- NEW PAGE -->
|
||||
<h3><a name='mxml_index_t'>mxml_index_t</a></h3>
|
||||
<hr noshade/>
|
||||
<h4>Description</h4>
|
||||
<p>An XML node index.</p>
|
||||
<h4>Definition</h4>
|
||||
<pre>
|
||||
typedef struct <a href='#mxml_index_s'>mxml_index_s</a> mxml_index_t;
|
||||
</pre>
|
||||
<!-- NEW PAGE -->
|
||||
<h3><a name='mxml_node_t'>mxml_node_t</a></h3>
|
||||
<hr noshade/>
|
||||
<h4>Description</h4>
|
||||
@ -1005,5 +1191,27 @@ union mxml_value_u
|
||||
<tr><td><tt>real</tt></td><td>Real number</td></tr>
|
||||
<tr><td><tt>text</tt></td><td>Text fragment</td></tr>
|
||||
</tbody></table></p>
|
||||
<!-- NEW PAGE -->
|
||||
<h2><a name='_variables'>Variables</a></h2>
|
||||
<ul>
|
||||
<li><a href='#num_callbacks'><tt>num_callbacks</tt></a></li>
|
||||
<li><a href='#sort_attr_name'><tt>sort_attr_name</tt></a></li>
|
||||
</ul>
|
||||
<!-- NEW PAGE -->
|
||||
<h3><a name='num_callbacks'>num_callbacks</a></h3>
|
||||
<hr noshade/>
|
||||
<h4>Definition</h4>
|
||||
<pre>
|
||||
static int num_callbacks = 1;
|
||||
</pre>
|
||||
<!-- NEW PAGE -->
|
||||
<h3><a name='sort_attr_name'>sort_attr_name</a></h3>
|
||||
<hr noshade/>
|
||||
<h4>Description</h4>
|
||||
<p>Delete an index.</p>
|
||||
<h4>Definition</h4>
|
||||
<pre>
|
||||
static const char * sort_attr_name;
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* "$Id: mxml-entity.c,v 1.3 2004/05/02 16:04:40 mike Exp $"
|
||||
* "$Id: mxml-entity.c,v 1.4 2004/05/16 05:25:38 mike Exp $"
|
||||
*
|
||||
* Character entity support code for Mini-XML, a small XML-like
|
||||
* file parsing library.
|
||||
@ -18,9 +18,14 @@
|
||||
*
|
||||
* Contents:
|
||||
*
|
||||
* mxmlEntityGetName() - Get the name that corresponds to the character
|
||||
* value.
|
||||
* mxmlEntityGetValue() - Get the character corresponding to a named entity.
|
||||
* mxmlEntityAddCallback() - Add a callback to convert entities to
|
||||
* Unicode.
|
||||
* mxmlEntityGetName() - Get the name that corresponds to the
|
||||
* character value.
|
||||
* mxmlEntityGetValue() - Get the character corresponding to a named
|
||||
* entity.
|
||||
* mxmlEntityRemoveCallback() - Remove a callback.
|
||||
* default_callback() - Lookup standard (X)HTML entities.
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -31,6 +36,40 @@
|
||||
#include "mxml.h"
|
||||
|
||||
|
||||
/*
|
||||
* Local functions...
|
||||
*/
|
||||
|
||||
static int default_callback(const char *name);
|
||||
|
||||
|
||||
/*
|
||||
* Callback array...
|
||||
*/
|
||||
|
||||
static int num_callbacks = 1;
|
||||
static int (*callbacks[100])(const char *name) =
|
||||
{
|
||||
default_callback
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* 'mxmlEntityAddCallback()' - Add a callback to convert entities to Unicode.
|
||||
*/
|
||||
|
||||
void
|
||||
mxmlEntityAddCallback(int (*cb)(const char *name))
|
||||
/* I - Callback function to add */
|
||||
{
|
||||
if (num_callbacks < (int)(sizeof(callbacks) / sizeof(callbacks[0])))
|
||||
{
|
||||
callbacks[num_callbacks] = cb;
|
||||
num_callbacks ++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 'mxmlEntityGetName()' - Get the name that corresponds to the character value.
|
||||
*
|
||||
@ -69,6 +108,54 @@ mxmlEntityGetName(int val) /* I - Character value */
|
||||
|
||||
int /* O - Character value or -1 on error */
|
||||
mxmlEntityGetValue(const char *name) /* I - Entity name */
|
||||
{
|
||||
int i; /* Looping var */
|
||||
int ch; /* Character value */
|
||||
|
||||
|
||||
for (i = 0; i < num_callbacks; i ++)
|
||||
if ((ch = (callbacks[i])(name)) >= 0)
|
||||
return (ch);
|
||||
|
||||
return (-1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 'mxmlEntityRemoveCallback()' - Remove a callback.
|
||||
*/
|
||||
|
||||
void
|
||||
mxmlEntityRemoveCallback(int (*cb)(const char *name))
|
||||
/* I - Callback function to remove */
|
||||
{
|
||||
int i; /* Looping var */
|
||||
|
||||
|
||||
for (i = 0; i < num_callbacks; i ++)
|
||||
if (cb == callbacks[i])
|
||||
{
|
||||
/*
|
||||
* Remove the callback...
|
||||
*/
|
||||
|
||||
num_callbacks --;
|
||||
|
||||
if (i < num_callbacks)
|
||||
memmove(callbacks + i, callbacks + i + 1,
|
||||
(num_callbacks - i) * sizeof(callbacks[0]));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 'default_callback()' - Lookup standard (X)HTML entities.
|
||||
*/
|
||||
|
||||
static int /* O - Unicode value or -1 */
|
||||
default_callback(const char *name) /* I - Entity name */
|
||||
{
|
||||
int diff, /* Difference between names */
|
||||
current, /* Current entity in search */
|
||||
@ -364,5 +451,5 @@ mxmlEntityGetValue(const char *name) /* I - Entity name */
|
||||
|
||||
|
||||
/*
|
||||
* End of "$Id: mxml-entity.c,v 1.3 2004/05/02 16:04:40 mike Exp $".
|
||||
* End of "$Id: mxml-entity.c,v 1.4 2004/05/16 05:25:38 mike Exp $".
|
||||
*/
|
||||
|
387
mxml-index.c
Normal file
387
mxml-index.c
Normal file
@ -0,0 +1,387 @@
|
||||
/*
|
||||
* "$Id: mxml-index.c,v 1.1 2004/05/16 05:25:38 mike Exp $"
|
||||
*
|
||||
* Index support code for Mini-XML, a small XML-like file parsing library.
|
||||
*
|
||||
* Copyright 2003-2004 by Michael Sweet.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* Contents:
|
||||
*
|
||||
* mxmlIndexDelete() - Delete an index.
|
||||
* mxmlIndexEnum() - Return the next node in the index.
|
||||
* mxmlIndexFind() - Find the next matching node.
|
||||
* mxmlIndexNew() - Create a new index.
|
||||
* mxmlIndexReset() - Return the first node in the index.
|
||||
* sort_attr() - Sort by attribute value...
|
||||
* sort_attr() - Sort by element name...
|
||||
* sort_element_attr() - Sort by element name and attribute value...
|
||||
*/
|
||||
|
||||
/*
|
||||
* Include necessary headers...
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "mxml.h"
|
||||
|
||||
|
||||
/*
|
||||
* Sort functions...
|
||||
*/
|
||||
|
||||
static int sort_attr(const void *a, const void *b);
|
||||
static int sort_element(const void *a, const void *b);
|
||||
static int sort_element_attr(const void *a, const void *b);
|
||||
|
||||
|
||||
/*
|
||||
* Sort attribute...
|
||||
*/
|
||||
|
||||
static const char *sort_attr_name;
|
||||
|
||||
|
||||
/*
|
||||
* 'mxmlIndexDelete()' - Delete an index.
|
||||
*/
|
||||
|
||||
void
|
||||
mxmlIndexDelete(mxml_index_t *ind) /* I - Index to delete */
|
||||
{
|
||||
/*
|
||||
* Range check input..
|
||||
*/
|
||||
|
||||
if (!ind)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Free memory...
|
||||
*/
|
||||
|
||||
if (ind->attr)
|
||||
free(ind->attr);
|
||||
|
||||
if (ind->alloc_nodes)
|
||||
free(ind->nodes);
|
||||
|
||||
free(ind);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 'mxmlIndexEnum()' - Return the next node in the index.
|
||||
*/
|
||||
|
||||
mxml_node_t * /* O - Next node or NULL if there is none */
|
||||
mxmlIndexEnum(mxml_index_t *ind) /* I - Index to enumerate */
|
||||
{
|
||||
/*
|
||||
* Range check input...
|
||||
*/
|
||||
|
||||
if (!ind)
|
||||
return (NULL);
|
||||
|
||||
/*
|
||||
* Return the next node...
|
||||
*/
|
||||
|
||||
if (ind->cur_node < ind->num_nodes)
|
||||
return (ind->nodes[ind->cur_node ++]);
|
||||
else
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 'mxmlIndexFind()' - Find the next matching node.
|
||||
*/
|
||||
|
||||
mxml_node_t * /* O - Node or NULL if none found */
|
||||
mxmlIndexFind(mxml_index_t *ind, /* I - Index to search */
|
||||
const char *element, /* I - Element name to find, if any */
|
||||
const char *value) /* I - Attribute value, if any */
|
||||
{
|
||||
int i, j; /* Looping vars */
|
||||
|
||||
|
||||
/*
|
||||
* Range check input...
|
||||
*/
|
||||
|
||||
if (!ind || (!ind->attr && value))
|
||||
return (NULL);
|
||||
|
||||
/*
|
||||
* If both element and value are NULL, just enumerate the nodes in the
|
||||
* index...
|
||||
*/
|
||||
|
||||
if (!element && !value)
|
||||
return (mxmlIndexEnum(ind));
|
||||
|
||||
/*
|
||||
* Find the node...
|
||||
*/
|
||||
|
||||
for (i = ind->cur_node; i < ind->num_nodes; i ++)
|
||||
{
|
||||
/*
|
||||
* Check the element name...
|
||||
*/
|
||||
|
||||
if (element)
|
||||
{
|
||||
if ((j = strcmp(element, ind->nodes[i]->value.element.name)) > 0)
|
||||
{
|
||||
/*
|
||||
* No more elements <= name...
|
||||
*/
|
||||
|
||||
ind->cur_node = ind->num_nodes;
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
else if (j < 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check the attribute value...
|
||||
*/
|
||||
|
||||
if (value)
|
||||
{
|
||||
if ((j = strcmp(value, mxmlElementGetAttr(ind->nodes[i], ind->attr))) > 0)
|
||||
{
|
||||
/*
|
||||
* No more attributes <= value...
|
||||
*/
|
||||
|
||||
ind->cur_node = ind->num_nodes;
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
else if (j != 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Got a match, return it...
|
||||
*/
|
||||
|
||||
ind->cur_node = i + 1;
|
||||
|
||||
return (ind->nodes[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we get this far, then we have no matches...
|
||||
*/
|
||||
|
||||
ind->cur_node = ind->num_nodes;
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 'mxmlIndexNew()' - Create a new index.
|
||||
*/
|
||||
|
||||
mxml_index_t * /* O - New index */
|
||||
mxmlIndexNew(mxml_node_t *node, /* I - XML node tree */
|
||||
const char *element, /* I - Element to index or NULL for all */
|
||||
const char *attr) /* I - Attribute to index or NULL for none */
|
||||
{
|
||||
mxml_index_t *ind; /* New index */
|
||||
mxml_node_t *current, /* Current node in index */
|
||||
**temp; /* Temporary node pointer array */
|
||||
|
||||
|
||||
/*
|
||||
* Range check input...
|
||||
*/
|
||||
|
||||
if (!node)
|
||||
return (NULL);
|
||||
|
||||
/*
|
||||
* Create a new index...
|
||||
*/
|
||||
|
||||
if ((ind = calloc(1, sizeof(mxml_index_t))) != NULL)
|
||||
return (NULL);
|
||||
|
||||
for (current = mxmlFindElement(node, node, element, attr, NULL, MXML_DESCEND);
|
||||
current;
|
||||
current = mxmlFindElement(current, node, element, attr, NULL, MXML_DESCEND))
|
||||
{
|
||||
if (ind->num_nodes >= ind->alloc_nodes)
|
||||
{
|
||||
if (!ind->alloc_nodes)
|
||||
temp = malloc(64 * sizeof(mxml_node_t *));
|
||||
else
|
||||
temp = realloc(ind->nodes, (ind->alloc_nodes + 64) * sizeof(mxml_node_t *));
|
||||
|
||||
if (!temp)
|
||||
{
|
||||
/*
|
||||
* Unable to allocate memory for the index, so abort...
|
||||
*/
|
||||
|
||||
mxml_error("Unable to allocate %d bytes for index: %s",
|
||||
(ind->alloc_nodes + 64) * sizeof(mxml_node_t *),
|
||||
strerror(errno));
|
||||
|
||||
mxmlIndexDelete(ind);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
ind->nodes = temp;
|
||||
ind->alloc_nodes += 64;
|
||||
}
|
||||
|
||||
ind->nodes[ind->num_nodes ++] = current;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sort nodes based upon the search criteria...
|
||||
*/
|
||||
|
||||
if (ind->num_nodes > 0)
|
||||
{
|
||||
if (!element && attr)
|
||||
{
|
||||
/*
|
||||
* Sort based upon the element name and attribute value...
|
||||
*/
|
||||
|
||||
sort_attr_name = attr;
|
||||
ind->attr = strdup(attr);
|
||||
|
||||
qsort(ind->nodes, ind->num_nodes, sizeof(mxml_node_t *),
|
||||
sort_element_attr);
|
||||
}
|
||||
else if (!element && !attr)
|
||||
{
|
||||
/*
|
||||
* Sort based upon the element name...
|
||||
*/
|
||||
|
||||
qsort(ind->nodes, ind->num_nodes, sizeof(mxml_node_t *),
|
||||
sort_element);
|
||||
}
|
||||
else if (attr)
|
||||
{
|
||||
/*
|
||||
* Sort based upon the attribute value...
|
||||
*/
|
||||
|
||||
sort_attr_name = attr;
|
||||
ind->attr = strdup(attr);
|
||||
|
||||
qsort(ind->nodes, ind->num_nodes, sizeof(mxml_node_t *),
|
||||
sort_attr);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the new index...
|
||||
*/
|
||||
|
||||
return (ind);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 'mxmlIndexReset()' - Return the first node in the index.
|
||||
*/
|
||||
|
||||
mxml_node_t * /* O - First node or NULL if there is none */
|
||||
mxmlIndexReset(mxml_index_t *ind) /* I - Index to reset */
|
||||
{
|
||||
/*
|
||||
* Range check input...
|
||||
*/
|
||||
|
||||
if (!ind)
|
||||
return (NULL);
|
||||
|
||||
/*
|
||||
* Set the index to the first element...
|
||||
*/
|
||||
|
||||
ind->cur_node = 0;
|
||||
|
||||
/*
|
||||
* Return the first node...
|
||||
*/
|
||||
|
||||
if (ind->num_nodes)
|
||||
return (ind->nodes);
|
||||
else
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 'sort_attr()' - Sort by attribute value...
|
||||
*/
|
||||
|
||||
static int /* O - Result of comparison */
|
||||
sort_attr(const void *a, /* I - First node */
|
||||
const void *b) /* I - Second node */
|
||||
{
|
||||
return (strcmp(mxmlElementGetAttr((mxml_node_t *)a, sort_attr_name),
|
||||
mxmlElementGetAttr((mxml_node_t *)b, sort_attr_name)));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 'sort_element()' - Sort by element name...
|
||||
*/
|
||||
|
||||
static int /* O - Result of comparison */
|
||||
sort_element(const void *a, /* I - First node */
|
||||
const void *b) /* I - Second node */
|
||||
{
|
||||
return (strcmp(((mxml_node_t *)a)->value.element.name,
|
||||
((mxml_node_t *)b)->value.element.name));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 'sort_element_attr()' - Sort by element name and attribute value...
|
||||
*/
|
||||
|
||||
static int /* O - Result of comparison */
|
||||
sort_element_attr(const void *a, /* I - First node */
|
||||
const void *b) /* I - Second node */
|
||||
{
|
||||
int i; /* Result of comparison */
|
||||
|
||||
|
||||
if ((i = strcmp(((mxml_node_t *)a)->value.element.name,
|
||||
((mxml_node_t *)b)->value.element.name)) != 0)
|
||||
return (i);
|
||||
else
|
||||
return (strcmp(mxmlElementGetAttr((mxml_node_t *)a, sort_attr_name),
|
||||
mxmlElementGetAttr((mxml_node_t *)b, sort_attr_name)));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* End of "$Id: mxml-index.c,v 1.1 2004/05/16 05:25:38 mike Exp $".
|
||||
*/
|
23
mxml.h
23
mxml.h
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* "$Id: mxml.h,v 1.19 2004/05/02 16:04:40 mike Exp $"
|
||||
* "$Id: mxml.h,v 1.20 2004/05/16 05:25:38 mike Exp $"
|
||||
*
|
||||
* Header file for Mini-XML, a small XML-like file parsing library.
|
||||
*
|
||||
@ -118,6 +118,15 @@ typedef struct mxml_node_s /**** An XML node. ****/
|
||||
mxml_value_t value; /* Node value */
|
||||
} mxml_node_t;
|
||||
|
||||
typedef struct mxml_index_s /**** An XML node index. ****/
|
||||
{
|
||||
char *attr; /* Attribute used for indexing or NULL */
|
||||
int num_nodes; /* Number of nodes in index */
|
||||
int alloc_nodes; /* Allocated nodes in index */
|
||||
int cur_node; /* Current node */
|
||||
mxml_node_t **nodes; /* Node array */
|
||||
} mxml_index_t;
|
||||
|
||||
|
||||
/*
|
||||
* C++ support...
|
||||
@ -137,11 +146,21 @@ 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,
|
||||
const char *value);
|
||||
extern void mxmlEntityAddCallback(int (*cb)(const char *name));
|
||||
extern const char *mxmlEntityGetName(int val);
|
||||
extern int mxmlEntityGetValue(const char *name);
|
||||
extern void mxmlEntityRemoveCallback(int (*cb)(const char *name));
|
||||
extern mxml_node_t *mxmlFindElement(mxml_node_t *node, mxml_node_t *top,
|
||||
const char *name, const char *attr,
|
||||
const char *value, int descend);
|
||||
extern void mxmlIndexDelete(mxml_index_t *ind);
|
||||
extern mxml_node_t *mxmlIndexEnum(mxml_index_t *ind);
|
||||
extern mxml_node_t *mxmlIndexFind(mxml_index_t *ind,
|
||||
const char *element,
|
||||
const char *value);
|
||||
extern mxml_index_t *mxmlIndexNew(mxml_node_t *node, const char *element,
|
||||
const char *attr);
|
||||
extern mxml_node_t *mxmlIndexReset(mxml_index_t *ind);
|
||||
extern mxml_node_t *mxmlLoadFile(mxml_node_t *top, FILE *fp,
|
||||
mxml_type_t (*cb)(mxml_node_t *));
|
||||
extern mxml_node_t *mxmlLoadString(mxml_node_t *top, const char *s,
|
||||
@ -206,5 +225,5 @@ extern mxml_type_t mxml_real_cb(mxml_node_t *node);
|
||||
|
||||
|
||||
/*
|
||||
* End of "$Id: mxml.h,v 1.19 2004/05/02 16:04:40 mike Exp $".
|
||||
* End of "$Id: mxml.h,v 1.20 2004/05/16 05:25:38 mike Exp $".
|
||||
*/
|
||||
|
115
mxml.xml
115
mxml.xml
@ -74,6 +74,13 @@ not an element.</description>
|
||||
<description>Attribute value</description>
|
||||
</argument>
|
||||
</function>
|
||||
<function name="mxmlEntityAddCallback">
|
||||
<description>Add a callback to convert entities to Unicode.</description>
|
||||
<argument name="(*cb)(const char *name)" direction="I">
|
||||
<type>int</type>
|
||||
<description>Callback function to add</description>
|
||||
</argument>
|
||||
</function>
|
||||
<function name="mxmlEntityGetName">
|
||||
<returnvalue>
|
||||
<type>const char *</type>
|
||||
@ -101,6 +108,13 @@ name is not known.</description>
|
||||
<description>Entity name</description>
|
||||
</argument>
|
||||
</function>
|
||||
<function name="mxmlEntityRemoveCallback">
|
||||
<description>Remove a callback.</description>
|
||||
<argument name="(*cb)(const char *name)" direction="I">
|
||||
<type>int</type>
|
||||
<description>Callback function to remove</description>
|
||||
</argument>
|
||||
</function>
|
||||
<function name="mxmlFindElement">
|
||||
<returnvalue>
|
||||
<type>mxml_node_t *</type>
|
||||
@ -141,6 +155,73 @@ constrains the search to a particular node's children.</description>
|
||||
<description>Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST</description>
|
||||
</argument>
|
||||
</function>
|
||||
<function name="mxmlIndexDelete">
|
||||
<description>Sort attribute...</description>
|
||||
<argument name="ind" direction="I">
|
||||
<type>mxml_index_t *</type>
|
||||
<description>Index to delete</description>
|
||||
</argument>
|
||||
</function>
|
||||
<function name="mxmlIndexEnum">
|
||||
<returnvalue>
|
||||
<type>mxml_node_t *</type>
|
||||
<description>Next node or NULL if there is none</description>
|
||||
</returnvalue>
|
||||
<description>Return the next node in the index.</description>
|
||||
<argument name="ind" direction="I">
|
||||
<type>mxml_index_t *</type>
|
||||
<description>Index to enumerate</description>
|
||||
</argument>
|
||||
</function>
|
||||
<function name="mxmlIndexFind">
|
||||
<returnvalue>
|
||||
<type>mxml_node_t *</type>
|
||||
<description>Node or NULL if none found</description>
|
||||
</returnvalue>
|
||||
<description>Find the next matching node.</description>
|
||||
<argument name="ind" direction="I">
|
||||
<type>mxml_index_t *</type>
|
||||
<description>Index to search</description>
|
||||
</argument>
|
||||
<argument name="element" direction="I">
|
||||
<type>const char *</type>
|
||||
<description>Element name to find, if any</description>
|
||||
</argument>
|
||||
<argument name="value" direction="I">
|
||||
<type>const char *</type>
|
||||
<description>Attribute value, if any</description>
|
||||
</argument>
|
||||
</function>
|
||||
<function name="mxmlIndexNew">
|
||||
<returnvalue>
|
||||
<type>mxml_index_t *</type>
|
||||
<description>New index</description>
|
||||
</returnvalue>
|
||||
<description>Create a new index.</description>
|
||||
<argument name="node" direction="I">
|
||||
<type>mxml_node_t *</type>
|
||||
<description>XML node tree</description>
|
||||
</argument>
|
||||
<argument name="element" direction="I">
|
||||
<type>const char *</type>
|
||||
<description>Element to index or NULL for all</description>
|
||||
</argument>
|
||||
<argument name="attr" direction="I">
|
||||
<type>const char *</type>
|
||||
<description>Attribute to index or NULL for none</description>
|
||||
</argument>
|
||||
</function>
|
||||
<function name="mxmlIndexReset">
|
||||
<returnvalue>
|
||||
<type>mxml_node_t *</type>
|
||||
<description>First node or NULL if there is none</description>
|
||||
</returnvalue>
|
||||
<description>Return the first node in the index.</description>
|
||||
<argument name="ind" direction="I">
|
||||
<type>mxml_index_t *</type>
|
||||
<description>Index to reset</description>
|
||||
</argument>
|
||||
</function>
|
||||
<function name="mxmlLoadFile">
|
||||
<returnvalue>
|
||||
<type>mxml_node_t *</type>
|
||||
@ -599,6 +680,33 @@ the walk to the node's children.</description>
|
||||
<type>struct mxml_value_s</type>
|
||||
<description>An XML element value.</description>
|
||||
</typedef>
|
||||
<struct name="mxml_index_s">
|
||||
<description>An XML node index.</description>
|
||||
<variable name="alloc_nodes">
|
||||
<type>int</type>
|
||||
<description>Allocated nodes in index</description>
|
||||
</variable>
|
||||
<variable name="attr">
|
||||
<type>char *</type>
|
||||
<description>Attribute used for indexing or NULL</description>
|
||||
</variable>
|
||||
<variable name="cur_node">
|
||||
<type>int</type>
|
||||
<description>Current node</description>
|
||||
</variable>
|
||||
<variable name="nodes">
|
||||
<type>mxml_node_t **</type>
|
||||
<description>Node array</description>
|
||||
</variable>
|
||||
<variable name="num_nodes">
|
||||
<type>int</type>
|
||||
<description>Number of nodes in index</description>
|
||||
</variable>
|
||||
</struct>
|
||||
<typedef name="mxml_index_t">
|
||||
<type>struct mxml_index_s</type>
|
||||
<description>An XML node index.</description>
|
||||
</typedef>
|
||||
<struct name="mxml_node_s">
|
||||
<description>An XML node.</description>
|
||||
<variable name="child">
|
||||
@ -713,4 +821,11 @@ the walk to the node's children.</description>
|
||||
<description>Text fragment</description>
|
||||
</variable>
|
||||
</union>
|
||||
<variable default="= 1" name="num_callbacks">
|
||||
<type>static int</type>
|
||||
</variable>
|
||||
<variable name="sort_attr_name">
|
||||
<type>static const char *</type>
|
||||
<description>Delete an index.</description>
|
||||
</variable>
|
||||
</mxmldoc>
|
||||
|
Loading…
Reference in New Issue
Block a user