parent
3e0c8eaa0e
commit
bc27547035
@ -1,633 +0,0 @@ |
||||
<html> |
||||
<body> |
||||
|
||||
<h1 align='right'><a name='ADVANCED'>Chapter 3 - More Mini-XML |
||||
Programming Techniques</a></h1> |
||||
|
||||
<p>This chapter shows additional ways to use the Mini-XML |
||||
library in your programs.</p> |
||||
|
||||
<h2><a name='LOAD_CALLBACKS'>Load Callbacks</a></h2> |
||||
|
||||
<p><a href='#LOAD_XML'>Chapter 2</a> introduced the <a |
||||
href='#mxmlLoadFile'><tt>mxmlLoadFile()</tt></a> and <a |
||||
href='#mxmlLoadString'><tt>mxmlLoadString()</tt></a> functions. |
||||
The last argument to these functions is a callback function |
||||
which is used to determine the value type of each data node in |
||||
an XML document.</p> |
||||
|
||||
<p>Mini-XML defines several standard callbacks for simple |
||||
XML data files:</p> |
||||
|
||||
<ul> |
||||
|
||||
<li><tt>MXML_INTEGER_CALLBACK</tt> - All data nodes |
||||
contain whitespace-separated integers.</li> |
||||
|
||||
<li><tt>MXML_OPAQUE_CALLBACK</tt> - All data nodes |
||||
contain opaque strings ("CDATA").</li> |
||||
|
||||
<li><tt>MXML_REAL_CALLBACK</tt> - All data nodes contain |
||||
whitespace-separated floating-point numbers.</li> |
||||
|
||||
<li><tt>MXML_TEXT_CALLBACK</tt> - All data nodes contain |
||||
whitespace-separated strings.</li> |
||||
|
||||
</ul> |
||||
|
||||
<p>You can provide your own callback functions for more complex |
||||
XML documents. Your callback function will receive a pointer to |
||||
the current element node and must return the value type of the |
||||
immediate children for that element node: <tt>MXML_INTEGER</tt>, |
||||
<tt>MXML_OPAQUE</tt>, <tt>MXML_REAL</tt>, or <tt>MXML_TEXT</tt>. |
||||
The function is called <i>after</i> the element and its |
||||
attributes have been read, so you can look at the element name, |
||||
attributes, and attribute values to determine the proper value |
||||
type to return.</p> |
||||
|
||||
<!-- NEED 2in --> |
||||
<p>The following callback function looks for an attribute named |
||||
"type" or the element name to determine the value type for its |
||||
child nodes:</p> |
||||
|
||||
<pre> |
||||
mxml_type_t |
||||
type_cb(mxml_node_t *node) |
||||
{ |
||||
const char *type; |
||||
|
||||
/* |
||||
* You can lookup attributes and/or use the |
||||
* element name, hierarchy, etc... |
||||
*/ |
||||
|
||||
type = mxmlElementGetAttr(node, "type"); |
||||
if (type == NULL) |
||||
type = mxmlGetElement(node); |
||||
|
||||
if (!strcmp(type, "integer")) |
||||
return (MXML_INTEGER); |
||||
else if (!strcmp(type, "opaque")) |
||||
return (MXML_OPAQUE); |
||||
else if (!strcmp(type, "real")) |
||||
return (MXML_REAL); |
||||
else |
||||
return (MXML_TEXT); |
||||
} |
||||
</pre> |
||||
|
||||
<p>To use this callback function, simply use the name when you |
||||
call any of the load functions:</p> |
||||
|
||||
<pre> |
||||
FILE *fp; |
||||
mxml_node_t *tree; |
||||
|
||||
fp = fopen("filename.xml", "r"); |
||||
tree = mxmlLoadFile(NULL, fp, <b>type_cb</b>); |
||||
fclose(fp); |
||||
</pre> |
||||
|
||||
|
||||
<h2><a name='SAVE_CALLBACKS'>Save Callbacks</a></h2> |
||||
|
||||
<p><a href='#LOAD_XML'>Chapter 2</a> also introduced the <a |
||||
href='#mxmlSaveFile'><tt>mxmlSaveFile()</tt></a>, <a |
||||
href='#mxmlSaveString'><tt>mxmlSaveString()</tt></a>, and <a |
||||
href='#mxmlSaveAllocString'><tt>mxmlSaveAllocString()</tt></a> |
||||
functions. The last argument to these functions is a callback |
||||
function which is used to automatically insert whitespace in an |
||||
XML document.</p> |
||||
|
||||
<p>Your callback function will be called up to four times for |
||||
each element node with a pointer to the node and a "where" value |
||||
of <tt>MXML_WS_BEFORE_OPEN</tt>, <tt>MXML_WS_AFTER_OPEN</tt>, |
||||
<tt>MXML_WS_BEFORE_CLOSE</tt>, or <tt>MXML_WS_AFTER_CLOSE</tt>. |
||||
The callback function should return <tt>NULL</tt> if no |
||||
whitespace should be added and the string to insert (spaces, |
||||
tabs, carriage returns, and newlines) otherwise.</p> |
||||
|
||||
<p>The following whitespace callback can be used to add |
||||
whitespace to XHTML output to make it more readable in a standard |
||||
text editor:</p> |
||||
|
||||
<pre> |
||||
const char * |
||||
whitespace_cb(mxml_node_t *node, |
||||
int where) |
||||
{ |
||||
const char *name; |
||||
|
||||
/* |
||||
* We can conditionally break to a new line |
||||
* before or after any element. These are |
||||
* just common HTML elements... |
||||
*/ |
||||
|
||||
name = mxmlGetElement(node); |
||||
|
||||
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")) |
||||
{ |
||||
/* |
||||
* Newlines before open and after |
||||
* close... |
||||
*/ |
||||
|
||||
if (where == MXML_WS_BEFORE_OPEN || |
||||
where == MXML_WS_AFTER_CLOSE) |
||||
return ("\n"); |
||||
} |
||||
else if (!strcmp(name, "dl") || |
||||
!strcmp(name, "ol") || |
||||
!strcmp(name, "ul")) |
||||
{ |
||||
/* |
||||
* Put a newline before and after list |
||||
* elements... |
||||
*/ |
||||
|
||||
return ("\n"); |
||||
} |
||||
else if (!strcmp(name, "dd") || |
||||
!strcmp(name, "dt") || |
||||
!strcmp(name, "li")) |
||||
{ |
||||
/* |
||||
* Put a tab before <li>'s, * <dd>'s, |
||||
* and <dt>'s, and a newline after them... |
||||
*/ |
||||
|
||||
if (where == MXML_WS_BEFORE_OPEN) |
||||
return ("\t"); |
||||
else if (where == MXML_WS_AFTER_CLOSE) |
||||
return ("\n"); |
||||
} |
||||
|
||||
/* |
||||
* Return NULL for no added whitespace... |
||||
*/ |
||||
|
||||
return (NULL); |
||||
} |
||||
</pre> |
||||
|
||||
<p>To use this callback function, simply use the name when you |
||||
call any of the save functions:</p> |
||||
|
||||
<pre> |
||||
FILE *fp; |
||||
mxml_node_t *tree; |
||||
|
||||
fp = fopen("filename.xml", "w"); |
||||
mxmlSaveFile(tree, fp, <b>whitespace_cb</b>); |
||||
fclose(fp); |
||||
</pre> |
||||
|
||||
|
||||
<!-- NEED 10 --> |
||||
<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 */ |
||||
} iso_date_time_t; |
||||
|
||||
int |
||||
load_custom(mxml_node_t *node, |
||||
const char *data) |
||||
{ |
||||
iso_date_time_t *dt; |
||||
struct tm tmdata; |
||||
|
||||
/* |
||||
* 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... |
||||
*/ |
||||
|
||||
mxmlSetCustom(node, data, destroy); |
||||
|
||||
/* |
||||
* 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> |
||||
|
||||
<!-- NEED 15 --> |
||||
<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 * |
||||
save_custom(mxml_node_t *node) |
||||
{ |
||||
char data[255]; |
||||
iso_date_time_t *dt; |
||||
|
||||
|
||||
dt = (iso_date_time_t *)mxmlGetCustom(node); |
||||
|
||||
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(<b>load_custom</b>, |
||||
<b>save_custom</b>); |
||||
</pre> |
||||
|
||||
|
||||
<!-- NEED 20 --> |
||||
<h2>Changing Node Values</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 to change node values safely and |
||||
without leaking memory.</p> |
||||
|
||||
<p>Existing nodes can be changed using the <a |
||||
href='#mxmlSetElement'><tt>mxmlSetElement()</tt></a>, <a |
||||
href='#mxmlSetInteger'><tt>mxmlSetInteger()</tt></a>, <a |
||||
href='#mxmlSetOpaque'><tt>mxmlSetOpaque()</tt></a>, <a |
||||
href='#mxmlSetReal'><tt>mxmlSetReal()</tt></a>, <a |
||||
href='#mxmlSetText'><tt>mxmlSetText()</tt></a>, and <a |
||||
href='#mxmlSetTextf'><tt>mxmlSetTextf()</tt></a> functions. For |
||||
example, use the following function call to change a text node |
||||
to contain the text "new" with leading whitespace:</p> |
||||
|
||||
<pre> |
||||
mxml_node_t *node; |
||||
|
||||
mxmlSetText(node, 1, "new"); |
||||
</pre> |
||||
|
||||
|
||||
<h2>Formatted Text</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. For example, use the following |
||||
function call to create a new text node containing a constructed |
||||
filename:</p> |
||||
|
||||
<pre> |
||||
mxml_node_t</a> *node; |
||||
|
||||
node = mxmlNewTextf(node, 1, "%s/%s", |
||||
path, filename); |
||||
</pre> |
||||
|
||||
|
||||
<h2>Indexing</h2> |
||||
|
||||
<p>Mini-XML provides functions for managing indices of nodes. |
||||
The current implementation provides the same functionality as |
||||
<a href='#mxmlFindElement'><tt>mxmlFindElement()</tt></a>. |
||||
The advantage of using an index is that searching and |
||||
enumeration of elements is significantly faster. The only |
||||
disadvantage is that each index is a static snapshot of the XML |
||||
document, so indices are not well suited to XML data that is |
||||
updated more often than it is searched. The overhead of creating |
||||
an index is approximately equal to walking the XML document |
||||
tree. Nodes in the index are sorted by element name and |
||||
attribute value.</p> |
||||
|
||||
<p>Indices are stored in <a href='#mxml_index_t'><tt>mxml_index_t</tt></a> |
||||
structures. The <a href='#mxmlIndexNew'><tt>mxmlIndexNew()</tt></a> function |
||||
creates a new index:</p> |
||||
|
||||
<pre> |
||||
mxml_node_t *tree; |
||||
mxml_index_t *ind; |
||||
|
||||
ind = mxmlIndexNew(tree, "element", |
||||
"attribute"); |
||||
</pre> |
||||
|
||||
<p>The first argument is the XML node tree to index. Normally this |
||||
will be a pointer to the <tt>?xml</tt> element.</p> |
||||
|
||||
<p>The second argument contains the element to index; passing |
||||
<tt>NULL</tt> indexes all element nodes alphabetically.</p> |
||||
|
||||
<p>The third argument contains the attribute to index; passing |
||||
<tt>NULL</tt> causes only the element name to be indexed.</p> |
||||
|
||||
<p>Once the index is created, the <a |
||||
href='#mxmlIndexEnum'><tt>mxmlIndexEnum()</tt></a>, <a |
||||
href='#mxmlIndexFind'><tt>mxmlIndexFind()</tt></a>, and <a |
||||
href='#mxmlIndexReset'><tt>mxmlIndexReset()</tt></a> functions |
||||
are used to access the nodes in the index. The <a |
||||
href='#mxmlIndexReset'><tt>mxmlIndexReset()</tt></a> function |
||||
resets the "current" node pointer in the index, allowing you to |
||||
do new searches and enumerations on the same index. Typically |
||||
you will call this function prior to your calls to <a |
||||
href='#mxmlIndexEnum'><tt>mxmlIndexEnum()</tt></a> and <a |
||||
href='#mxmlIndexFind'><tt>mxmlIndexFind()</tt></a>.</p> |
||||
|
||||
<p>The <a href='#mxmlIndexEnum'><tt>mxmlIndexEnum()</tt></a> |
||||
function enumerates each of the nodes in the index and can be |
||||
used in a loop as follows:</p> |
||||
|
||||
<pre> |
||||
mxml_node_t *node; |
||||
|
||||
mxmlIndexReset(ind); |
||||
|
||||
while ((node = mxmlIndexEnum(ind)) != NULL) |
||||
{ |
||||
// do something with node |
||||
} |
||||
</pre> |
||||
|
||||
<p>The <a href='#mxmlIndexFind'><tt>mxmlIndexFind()</tt></a> |
||||
function locates the next occurrence of the named element and |
||||
attribute value in the index. It can be used to find all |
||||
matching elements in an index, as follows:</p> |
||||
|
||||
<pre> |
||||
mxml_node_t *node; |
||||
|
||||
mxmlIndexReset(ind); |
||||
|
||||
while ((node = mxmlIndexFind(ind, "element", |
||||
"attr-value")) |
||||
!= NULL) |
||||
{ |
||||
// do something with node |
||||
} |
||||
</pre> |
||||
|
||||
<p>The second and third arguments represent the element name and |
||||
attribute value, respectively. A <tt>NULL</tt> pointer is used |
||||
to return all elements or attributes in the index. Passing |
||||
<tt>NULL</tt> for both the element name and attribute value |
||||
is equivalent to calling <tt>mxmlIndexEnum</tt>.</p> |
||||
|
||||
<p>When you are done using the index, delete it using the |
||||
<a href='#mxmlIndexDelete()'><tt>mxmlIndexDelete()</tt></a> |
||||
function:</p> |
||||
|
||||
<pre> |
||||
mxmlIndexDelete(ind); |
||||
</pre> |
||||
|
||||
<h2>SAX (Stream) Loading of Documents</h2> |
||||
|
||||
<p>Mini-XML supports an implementation of the Simple API for XML |
||||
(SAX) which allows you to load and process an XML document as a |
||||
stream of nodes. Aside from allowing you to process XML documents of |
||||
any size, the Mini-XML implementation also allows you to retain |
||||
portions of the document in memory for later processing.</p> |
||||
|
||||
<p>The <a href='#mxmlSAXLoad'><tt>mxmlSAXLoadFd</tt></a>, <a |
||||
href='#mxmlSAXLoadFile'><tt>mxmlSAXLoadFile</tt></a>, and <a |
||||
href='#mxmlSAXLoadString'><tt>mxmlSAXLoadString</tt></a> functions |
||||
provide the SAX loading APIs. Each function works like the |
||||
corresponding <tt>mxmlLoad</tt> function but uses a callback to |
||||
process each node as it is read.</p> |
||||
|
||||
<p>The callback function receives the node, an event code, and |
||||
a user data pointer you supply:</p> |
||||
|
||||
<pre> |
||||
void |
||||
sax_cb(mxml_node_t *node, |
||||
mxml_sax_event_t event, |
||||
void *data) |
||||
{ |
||||
... do something ... |
||||
} |
||||
</pre> |
||||
|
||||
<p>The event will be one of the following:</p> |
||||
|
||||
<ul> |
||||
|
||||
<li><tt>MXML_SAX_CDATA</tt> - CDATA was just read</li> |
||||
|
||||
<li><tt>MXML_SAX_COMMENT</tt> - A comment was just read</li> |
||||
|
||||
<li><tt>MXML_SAX_DATA</tt> - Data (custom, integer, opaque, real, or text) was just read</li> |
||||
|
||||
<li><tt>MXML_SAX_DIRECTIVE</tt> - A processing directive was just read</li> |
||||
|
||||
<li><tt>MXML_SAX_ELEMENT_CLOSE</tt> - A close element was just read (<tt></element></tt>)</li> |
||||
|
||||
<li><tt>MXML_SAX_ELEMENT_OPEN</tt> - An open element was just read (<tt><element></tt>)</li> |
||||
|
||||
</ul> |
||||
|
||||
<p>Elements are <em>released</em> after the close element is |
||||
processed. All other nodes are released after they are processed. |
||||
The SAX callback can <em>retain</em> the node using the <a |
||||
href='#mxmlRetain'><tt>mxmlRetain</tt></a> function. For example, |
||||
the following SAX callback will retain all nodes, effectively |
||||
simulating a normal in-memory load:</p> |
||||
|
||||
<pre> |
||||
void |
||||
sax_cb(mxml_node_t *node, |
||||
mxml_sax_event_t event, |
||||
void *data) |
||||
{ |
||||
if (event != MXML_SAX_ELEMENT_CLOSE) |
||||
mxmlRetain(node); |
||||
} |
||||
</pre> |
||||
|
||||
<p>More typically the SAX callback will only retain a small portion |
||||
of the document that is needed for post-processing. For example, the |
||||
following SAX callback will retain the title and headings in an |
||||
XHTML file. It also retains the (parent) elements like <tt><html></tt>, <tt><head></tt>, and <tt><body></tt>, and processing |
||||
directives like <tt><?xml ... ?></tt> and <tt><!DOCTYPE ... ></tt>:</p> |
||||
|
||||
<!-- NEED 10 --> |
||||
<pre> |
||||
void |
||||
sax_cb(mxml_node_t *node, |
||||
mxml_sax_event_t event, |
||||
void *data) |
||||
{ |
||||
if (event == MXML_SAX_ELEMENT_OPEN) |
||||
{ |
||||
/* |
||||
* Retain headings and titles... |
||||
*/ |
||||
|
||||
char *name = mxmlGetElement(node); |
||||
|
||||
if (!strcmp(name, "html") || |
||||
!strcmp(name, "head") || |
||||
!strcmp(name, "title") || |
||||
!strcmp(name, "body") || |
||||
!strcmp(name, "h1") || |
||||
!strcmp(name, "h2") || |
||||
!strcmp(name, "h3") || |
||||
!strcmp(name, "h4") || |
||||
!strcmp(name, "h5") || |
||||
!strcmp(name, "h6")) |
||||
mxmlRetain(node); |
||||
} |
||||
else if (event == MXML_SAX_DIRECTIVE) |
||||
mxmlRetain(node); |
||||
else if (event == MXML_SAX_DATA) |
||||
{ |
||||
if (mxmlGetRefCount(mxmlGetParent(node)) > 1) |
||||
{ |
||||
/* |
||||
* If the parent was retained, then retain |
||||
* this data node as well. |
||||
*/ |
||||
|
||||
mxmlRetain(node); |
||||
} |
||||
} |
||||
} |
||||
</pre> |
||||
|
||||
<p>The resulting skeleton document tree can then be searched just |
||||
like one loaded using the <tt>mxmlLoad</tt> functions. For example, |
||||
a filter that reads an XHTML document from stdin and then shows the |
||||
title and headings in the document would look like:</p> |
||||
|
||||
<pre> |
||||
mxml_node_t *doc, *title, *body, *heading; |
||||
|
||||
doc = mxmlSAXLoadFd(NULL, 0, |
||||
MXML_TEXT_CALLBACK, |
||||
<b>sax_cb</b>, NULL); |
||||
|
||||
title = mxmlFindElement(doc, doc, "title", |
||||
NULL, NULL, |
||||
MXML_DESCEND); |
||||
|
||||
if (title) |
||||
print_children(title); |
||||
|
||||
body = mxmlFindElement(doc, doc, "body", |
||||
NULL, NULL, |
||||
MXML_DESCEND); |
||||
|
||||
if (body) |
||||
{ |
||||
for (heading = mxmlGetFirstChild(body); |
||||
heading; |
||||
heading = mxmlGetNextSibling(heading)) |
||||
print_children(heading); |
||||
} |
||||
</pre> |
||||
|
||||
</body> |
||||
</html> |
@ -1,590 +0,0 @@ |
||||
<html> |
||||
<body> |
||||
|
||||
<h1 align='right'><a name='BASICS'>Chapter 2 - Getting Started |
||||
with Mini-XML</a></h1> |
||||
|
||||
<p>This chapter describes how to write programs that use Mini-XML to |
||||
access data in an XML file. Mini-XML provides the following |
||||
functionality:</p> |
||||
|
||||
<ul> |
||||
<li>Reading of UTF-8 and UTF-16 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>SAX (streamed) reading of XML files and strings to minimize memory usage.</li> |
||||
<li>Supports arbitrary element names, attributes, and attribute values with no preset limits, just available memory.</li> |
||||
<li>Supports integer, real, opaque ("cdata"), and text data types in "leaf" nodes.</li> |
||||
<li>Functions for creating and managing trees of data.</li> |
||||
<li>"Find" and "walk" functions for easily locating and navigating trees of data.</li> |
||||
</ul> |
||||
|
||||
<p>Mini-XML doesn't do validation or other types of processing on the data based upon schema files or other sources of definition information.</p> |
||||
|
||||
|
||||
<h2>The Basics</h2> |
||||
|
||||
<p>Mini-XML provides a single header file which you include:</p> |
||||
|
||||
<pre> |
||||
#include <mxml.h> |
||||
</pre> |
||||
|
||||
<p>The Mini-XML library is included with your program using the |
||||
<kbd>-lmxml</kbd> option:</p> |
||||
|
||||
<pre> |
||||
<kbd>gcc -o myprogram myprogram.c -lmxml ENTER</kbd> |
||||
</pre> |
||||
|
||||
<p>If you have the <tt>pkg-config(1)</tt> software installed, |
||||
you can use it to determine the proper compiler and linker options |
||||
for your installation:</p> |
||||
|
||||
<pre> |
||||
<kbd>pkg-config --cflags mxml ENTER</kbd> |
||||
<kbd>pkg-config --libs mxml ENTER</kbd> |
||||
</pre> |
||||
|
||||
<h2>Nodes</h2> |
||||
|
||||
<p>Every piece of information in an XML file is stored in memory in "nodes". |
||||
Nodes are defined by the <a href='#mxml_node_t'><tt>mxml_node_t</tt></a> |
||||
structure. Each node has a typed value, optional user data, a parent node, |
||||
sibling nodes (previous and next), and potentially child nodes.</p> |
||||
|
||||
<p>For example, if you have an XML file like the following:</p> |
||||
|
||||
<pre> |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<data> |
||||
<node>val1</node> |
||||
<node>val2</node> |
||||
<node>val3</node> |
||||
<group> |
||||
<node>val4</node> |
||||
<node>val5</node> |
||||
<node>val6</node> |
||||
</group> |
||||
<node>val7</node> |
||||
<node>val8</node> |
||||
</data> |
||||
</pre> |
||||
|
||||
<p>the node tree for the file would look like the following in memory:</p> |
||||
|
||||
<pre> |
||||
?xml version="1.0" encoding="utf-8"? |
||||
| |
||||
data |
||||
| |
||||
node - node - node - group - node - node |
||||
| | | | | | |
||||
val1 val2 val3 | val7 val8 |
||||
| |
||||
node - node - node |
||||
| | | |
||||
val4 val5 val6 |
||||
</pre> |
||||
|
||||
<p>where "-" is a pointer to the sibling node and "|" is a pointer |
||||
to the first child or parent node.</p> |
||||
|
||||
<p>The <a href="#mxmlGetType"><tt>mxmlGetType</tt></a> function gets the type of |
||||
a node, one of <tt>MXML_CUSTOM</tt>, <tt>MXML_ELEMENT</tt>, |
||||
<tt>MXML_INTEGER</tt>, <tt>MXML_OPAQUE</tt>, <tt>MXML_REAL</tt>, or |
||||
<tt>MXML_TEXT</tt>. The parent and sibling nodes are accessed using the |
||||
<a href="#mxmlGetParent"><tt>mxmlGetParent</tt></a>, |
||||
<a href="#mxmlGetNext"><tt>mxmlGetNext</tt></a>, and |
||||
<a href="#mxmlGetPrevious"><tt>mxmlGetPrevious</tt></a> functions. The |
||||
<a href="#mxmlGetUserData"><tt>mxmlGetUserData</tt></a> function gets any user |
||||
data associated with the node.</p> |
||||
|
||||
<h3>CDATA Nodes</h3> |
||||
|
||||
<p>CDATA (<tt>MXML_ELEMENT</tt>) nodes are created using the |
||||
<a href="#mxmlNewCDATA"><tt>mxmlNewCDATA</tt></a> function. The |
||||
<a href="#mxmlGetCDATA"><tt>mxmlGetCDATA</tt></a> function retrieves the |
||||
CDATA string pointer for a node.</p> |
||||
|
||||
<blockquote><b>Note:</b> |
||||
|
||||
<p>CDATA nodes are currently stored in memory as special elements. This will |
||||
be changed in a future major release of Mini-XML.</p> |
||||
</blockquote> |
||||
|
||||
<h3>Custom Nodes</h3> |
||||
|
||||
<p>Custom (<tt>MXML_CUSTOM</tt>) nodes are created using the |
||||
<a href="#mxmlNewCustom"><tt>mxmlNewCustom</tt></a> function or using a custom |
||||
load callback specified using the |
||||
<a href="#mxmlSetCustomHandlers"><tt>mxmlSetCustomHandlers</tt></a> function. |
||||
The <a href="#mxmlGetCustom"><tt>mxmlGetCustom</tt></a> function retrieves the |
||||
custom value pointer for a node.</p> |
||||
|
||||
<h3>Comment Nodes</h3> |
||||
|
||||
<p>Comment (<tt>MXML_ELEMENT</tt>) nodes are created using the |
||||
<a href="#mxmlNewElement"><tt>mxmlNewElement</tt></a> function. The |
||||
<a href="#mxmlGetElement"><tt>mxmlGetElement</tt></a> function retrieves the |
||||
comment string pointer for a node, including the surrounding "!--" and "--" |
||||
characters.</p> |
||||
|
||||
<blockquote><b>Note:</b> |
||||
|
||||
<p>Comment nodes are currently stored in memory as special elements. This will |
||||
be changed in a future major release of Mini-XML.</p> |
||||
</blockquote> |
||||
|
||||
<h3>Element Nodes</h3> |
||||
|
||||
<p>Element (<tt>MXML_ELEMENT</tt>) nodes are created using the |
||||
<a href="#mxmlNewElement"><tt>mxmlNewElement</tt></a> function. The |
||||
<a href="#mxmlGetElement"><tt>mxmlGetElement</tt></a> function retrieves the |
||||
element name, the |
||||
<a href="#mxmlElementGetAttr"><tt>mxmlElementGetAttr</tt></a> function retrieves |
||||
the value string for a named attribute associated with the element, and the |
||||
<a href="#mxmlGetFirstChild"><tt>mxmlGetFirstChild</tt></a> and |
||||
<a href="#mxmlGetLastChild"><tt>mxmlGetLastChild</tt></a> functions retrieve the |
||||
first and last child nodes for the element, respectively.</p> |
||||
|
||||
<h3>Integer Nodes</h3> |
||||
|
||||
<p>Integer (<tt>MXML_INTEGER</tt>) nodes are created using the |
||||
<a href="#mxmlNewInteger"><tt>mxmlNewInteger</tt></a> function. The |
||||
<a href="#mxmlGetInteger"><tt>mxmlGetInteger</tt></a> function retrieves the |
||||
integer value for a node.</p> |
||||
|
||||
<h3>Opaque String Nodes</h3> |
||||
|
||||
<p>Opaque string (<tt>MXML_OPAQUE</tt>) nodes are created using the |
||||
<a href="#mxmlNewOpaque"><tt>mxmlNewOpaque</tt></a> function. The |
||||
<a href="#mxmlGetOpaque"><tt>mxmlGetOpaque</tt></a> function retrieves the |
||||
opaque string pointer for a node. Opaque nodes are like string nodes but |
||||
preserve all whitespace between nodes.</p> |
||||
|
||||
<h3>Text String Nodes</h3> |
||||
|
||||
<p>Text string (<tt>MXML_TEXT</tt>) nodes are created using the |
||||
<a href="#mxmlNewText"><tt>mxmlNewText</tt></a> and |
||||
<a href="#mxmlNewTextf"><tt>mxmlNewTextf</tt></a> functions. Each text node |
||||
consists of a single word string and (leading) whitespace value - the |
||||
<a href="#mxmlGetText"><tt>mxmlGetText</tt></a> function retrieves the |
||||
string pointer and whitespace value for a node.</p> |
||||
|
||||
<!-- NEED 12 --> |
||||
<h3>Processing Instruction Nodes</h3> |
||||
|
||||
<p>Processing instruction (<tt>MXML_ELEMENT</tt>) nodes are created using the |
||||
<a href="#mxmlNewElement"><tt>mxmlNewElement</tt></a> function. The |
||||
<a href="#mxmlGetElement"><tt>mxmlGetElement</tt></a> function retrieves the |
||||
processing instruction string for a node, including the surrounding "?" |
||||
characters.</p> |
||||
|
||||
<blockquote><b>Note:</b> |
||||
|
||||
<p>Processing instruction nodes are currently stored in memory as special |
||||
elements. This will be changed in a future major release of Mini-XML.</p> |
||||
</blockquote> |
||||
|
||||
<h3>Real Number Nodes</h3> |
||||
|
||||
<p>Real number (<tt>MXML_REAL</tt>) nodes are created using the |
||||
<a href="#mxmlNewReal"><tt>mxmlNewReal</tt></a> function. The |
||||
<a href="#mxmlGetReal"><tt>mxmlGetReal</tt></a> function retrieves the |
||||
CDATA string pointer for a node.</p> |
||||
|
||||
<!-- NEED 15 --> |
||||
<h3>XML Declaration Nodes</h3> |
||||
|
||||
<p>XML declaration (<tt>MXML_ELEMENT</tt>) nodes are created using the |
||||
<a href="#mxmlNewXML"><tt>mxmlNewXML</tt></a> function. The |
||||
<a href="#mxmlGetElement"><tt>mxmlGetElement</tt></a> function retrieves the |
||||
XML declaration string for a node, including the surrounding "?" characters.</p> |
||||
|
||||
<blockquote><b>Note:</b> |
||||
|
||||
<p>XML declaration nodes are currently stored in memory as special elements. |
||||
This will be changed in a future major release of Mini-XML.</p> |
||||
</blockquote> |
||||
|
||||
|
||||
<!-- NEW PAGE --> |
||||
<h2>Creating XML Documents</h2> |
||||
|
||||
<p>You can create and update XML documents in memory using the |
||||
various <tt>mxmlNew</tt> functions. The following code will |
||||
create the XML document described in the previous section:</p> |
||||
|
||||
<pre> |
||||
mxml_node_t *xml; /* <?xml ... ?> */ |
||||
mxml_node_t *data; /* <data> */ |
||||
mxml_node_t *node; /* <node> */ |
||||
mxml_node_t *group; /* <group> */ |
||||
|
||||
xml = mxmlNewXML("1.0"); |
||||
|
||||
data = mxmlNewElement(xml, "data"); |
||||
|
||||
node = mxmlNewElement(data, "node"); |
||||
mxmlNewText(node, 0, "val1"); |
||||
node = mxmlNewElement(data, "node"); |
||||
mxmlNewText(node, 0, "val2"); |
||||
node = mxmlNewElement(data, "node"); |
||||
mxmlNewText(node, 0, "val3"); |
||||
|
||||
group = mxmlNewElement(data, "group"); |
||||
|
||||
node = mxmlNewElement(group, "node"); |
||||
mxmlNewText(node, 0, "val4"); |
||||
node = mxmlNewElement(group, "node"); |
||||
mxmlNewText(node, 0, "val5"); |
||||
node = mxmlNewElement(group, "node"); |
||||
mxmlNewText(node, 0, "val6"); |
||||
|
||||
node = mxmlNewElement(data, "node"); |
||||
mxmlNewText(node, 0, "val7"); |
||||
node = mxmlNewElement(data, "node"); |
||||
mxmlNewText(node, 0, "val8"); |
||||
</pre> |
||||
|
||||
<!-- NEED 6 --> |
||||
<p>We start by creating the declaration node common to all XML files using the |
||||
<a href="#mxmlNewXML"><tt>mxmlNewXML</tt></a> function:</p> |
||||
|
||||
<pre> |
||||
xml = mxmlNewXML("1.0"); |
||||
</pre> |
||||
|
||||
<p>We then create the <tt><data></tt> node used for this document using |
||||
the <a href="#mxmlNewElement"><tt>mxmlNewElement</tt></a> function. The first |
||||
argument specifies the parent node (<tt>xml</tt>) while the second specifies the |
||||
element name (<tt>data</tt>):</p> |
||||
|
||||
<pre> |
||||
data = mxmlNewElement(xml, "data"); |
||||
</pre> |
||||
|
||||
<p>Each <tt><node>...</node></tt> in the file is created using the |
||||
<tt>mxmlNewElement</tt> and <a href="#mxmlNewText"><tt>mxmlNewText</tt></a> |
||||
functions. The first argument of <tt>mxmlNewText</tt> specifies the parent node |
||||
(<tt>node</tt>). The second argument specifies whether whitespace appears before |
||||
the text - 0 or false in this case. The last argument specifies the actual text |
||||
to add:</p> |
||||
|
||||
<pre> |
||||
node = mxmlNewElement(data, "node"); |
||||
mxmlNewText(node, 0, "val1"); |
||||
</pre> |
||||
|
||||
<p>The resulting in-memory XML document can then be saved or processed just like |
||||
one loaded from disk or a string.</p> |
||||
|
||||
<!-- NEED 15 --> |
||||
<h2>Loading XML</h2> |
||||
|
||||
<p>You load an XML file using the <a |
||||
href='#mxmlLoadFile'><tt>mxmlLoadFile</tt></a> |
||||
function:</p> |
||||
|
||||
<pre> |
||||
FILE *fp; |
||||
mxml_node_t *tree; |
||||
|
||||
fp = fopen("filename.xml", "r"); |
||||
tree = mxmlLoadFile(NULL, fp, |
||||
MXML_OPAQUE_CALLBACK); |
||||
fclose(fp); |
||||
</pre> |
||||
|
||||
<p>The first argument specifies an existing XML parent node, if |
||||
any. Normally you will pass <tt>NULL</tt> for this argument |
||||
unless you are combining multiple XML sources. The XML file must |
||||
contain a complete XML document including the <tt>?xml</tt> |
||||
element if the parent node is <tt>NULL</tt>.</p> |
||||
|
||||
<p>The second argument specifies the stdio file to read from, as |
||||
opened by <tt>fopen()</tt> or <tt>popen()</tt>. You can also use |
||||
<tt>stdin</tt> if you are implementing an XML filter |
||||
program.</p> |
||||
|
||||
<p>The third argument specifies a callback function which returns |
||||
the value type of the immediate children for a new element node: |
||||
<tt>MXML_CUSTOM</tt>, <tt>MXML_IGNORE</tt>, |
||||
<tt>MXML_INTEGER</tt>, <tt>MXML_OPAQUE</tt>, <tt>MXML_REAL</tt>, |
||||
or <tt>MXML_TEXT</tt>. Load callbacks are described in detail in |
||||
<a href='#LOAD_CALLBACKS'>Chapter 3</a>. The example code uses |
||||
the <tt>MXML_OPAQUE_CALLBACK</tt> constant which specifies that all |
||||
data nodes in the document contain opaque string values with whitespace |
||||
preserved. Other standard callbacks include |
||||
<tt>MXML_IGNORE_CALLBACK</tt>, <tt>MXML_INTEGER_CALLBACK</tt>, |
||||
<tt>MXML_REAL_CALLBACK</tt>, and |
||||
<tt>MXML_TEXT_CALLBACK</tt>.</p> |
||||
|
||||
<p>The <a href='#mxmlLoadString'><tt>mxmlLoadString</tt></a> |
||||
function loads XML node trees from a string:</p> |
||||
|
||||
<!-- NEED 10 --> |
||||
<pre> |
||||
char buffer[8192]; |
||||
mxml_node_t *tree; |
||||
|
||||
... |
||||
tree = mxmlLoadString(NULL, buffer, |
||||
MXML_OPAQUE_CALLBACK); |
||||
</pre> |
||||
|
||||
<p>The first and third arguments are the same as used for |
||||
<tt>mxmlLoadFile()</tt>. The second argument specifies the |
||||
string or character buffer to load and must be a complete XML |
||||
document including the <tt>?xml</tt> element if the parent node |
||||
is <tt>NULL</tt>.</p> |
||||
|
||||
|
||||
<!-- NEED 15 --> |
||||
<h2>Saving XML</h2> |
||||
|
||||
<p>You save an XML file using the <a |
||||
href='#mxmlSaveFile'><tt>mxmlSaveFile</tt></a> function:</p> |
||||
|
||||
<pre> |
||||
FILE *fp; |
||||
mxml_node_t *tree; |
||||
|
||||
fp = fopen("filename.xml", "w"); |
||||
mxmlSaveFile(tree, fp, MXML_NO_CALLBACK); |
||||
fclose(fp); |
||||
</pre> |
||||
|
||||
<p>The first argument is the XML node tree to save. It should |
||||
normally be a pointer to the top-level <tt>?xml</tt> node in |
||||
your XML document.</p> |
||||
|
||||
<p>The second argument is the stdio file to write to, as opened |
||||
by <tt>fopen()</tt> or <tt>popen()</tt>. You can also use |
||||
<tt>stdout</tt> if you are implementing an XML filter |
||||
program.</p> |
||||
|
||||
<p>The third argument is the whitespace callback to use when |
||||
saving the file. Whitespace callbacks are covered in detail in <a |
||||
href='SAVE_CALLBACKS'>Chapter 3</a>. The previous example code |
||||
uses the <tt>MXML_NO_CALLBACK</tt> constant to specify that no |
||||
special whitespace handling is required.</p> |
||||
|
||||
<p>The <a |
||||
href='#mxmlSaveAllocString'><tt>mxmlSaveAllocString</tt></a>, |
||||
and <a href='#mxmlSaveString'><tt>mxmlSaveString</tt></a> |
||||
functions save XML node trees to strings:</p> |
||||
|
||||
<pre> |
||||
char buffer[8192]; |
||||
char *ptr; |
||||
mxml_node_t *tree; |
||||
|
||||
... |
||||
mxmlSaveString(tree, buffer, sizeof(buffer), |
||||
MXML_NO_CALLBACK); |
||||
|
||||
... |
||||
ptr = mxmlSaveAllocString(tree, MXML_NO_CALLBACK); |
||||
</pre> |
||||
|
||||
<p>The first and last arguments are the same as used for |
||||
<tt>mxmlSaveFile()</tt>. The <tt>mxmlSaveString</tt> function |
||||
takes pointer and size arguments for saving the XML document to |
||||
a fixed-size buffer, while <tt>mxmlSaveAllocString()</tt> |
||||
returns a string buffer that was allocated using |
||||
<tt>malloc()</tt>.</p> |
||||
|
||||
<!-- NEED 15 --> |
||||
<h3>Controlling Line Wrapping</h3> |
||||
|
||||
<p>When saving XML documents, Mini-XML normally wraps output |
||||
lines at column 75 so that the text is readable in terminal |
||||
windows. The <a |
||||
href='#mxmlSetWrapMargin'><tt>mxmlSetWrapMargin</tt></a> function |
||||
overrides the default wrap margin:</p> |
||||
|
||||
<pre> |
||||
/* Set the margin to 132 columns */ |
||||
mxmlSetWrapMargin(132); |
||||
|
||||
/* Disable wrapping */ |
||||
mxmlSetWrapMargin(0); |
||||
</pre> |
||||
|
||||
<h2>Memory Management</h2> |
||||
|
||||
<p>Once you are done with the XML data, use the <a |
||||
href="#mxmlDelete"><tt>mxmlDelete</tt></a> function to recursively |
||||
free the memory that is used for a particular node or the entire |
||||
tree:</p> |
||||
|
||||
<pre> |
||||
mxmlDelete(tree); |
||||
</pre> |
||||
|
||||
<p>You can also use reference counting to manage memory usage. The |
||||
<a href="#mxmlRetain"><tt>mxmlRetain</tt></a> and |
||||
<a href="#mxmlRelease"><tt>mxmlRelease</tt></a> functions increment and |
||||
decrement a node's use count, respectively. When the use count goes to 0, |
||||
<tt>mxmlRelease</tt> will automatically call <tt>mxmlDelete</tt> to actually |
||||
free the memory used by the node tree. New nodes automatically start with a |
||||
use count of 1.</p> |
||||
|
||||
|
||||
<!-- NEW PAGE--> |
||||
<h2>Finding and Iterating Nodes</h2> |
||||
|
||||
<p>The <a |
||||
href='#mxmlWalkPrev'><tt>mxmlWalkPrev</tt></a> |
||||
and <a |
||||
href='#mxmlWalkNext'><tt>mxmlWalkNext</tt></a>functions |
||||
can be used to iterate through the XML node tree:</p> |
||||
|
||||
<pre> |
||||
mxml_node_t *node; |
||||
|
||||
node = mxmlWalkPrev(current, tree, |
||||
MXML_DESCEND); |
||||
|
||||
node = mxmlWalkNext(current, tree, |
||||
MXML_DESCEND); |
||||
</pre> |
||||
|
||||
<p>In addition, you can find a named element/node using the <a |
||||
href='#mxmlFindElement'><tt>mxmlFindElement</tt></a> |
||||
function:</p> |
||||
|
||||
<pre> |
||||
mxml_node_t *node; |
||||
|
||||
node = mxmlFindElement(tree, tree, "name", |
||||
"attr", "value", |
||||
MXML_DESCEND); |
||||
</pre> |
||||
|
||||
<p>The <tt>name</tt>, <tt>attr</tt>, and <tt>value</tt> |
||||
arguments can be passed as <tt>NULL</tt> to act as wildcards, |
||||
e.g.:</p> |
||||
|
||||
<!-- NEED 4 --> |
||||
<pre> |
||||
/* Find the first "a" element */ |
||||
node = mxmlFindElement(tree, tree, "a", |
||||
NULL, NULL, |
||||
MXML_DESCEND); |
||||
</pre> |
||||
<!-- NEED 5 --> |
||||
<pre> |
||||
/* Find the first "a" element with "href" |
||||
attribute */ |
||||
node = mxmlFindElement(tree, tree, "a", |
||||
"href", NULL, |
||||
MXML_DESCEND); |
||||
</pre> |
||||
<!-- NEED 6 --> |
||||
<pre> |
||||
/* Find the first "a" element with "href" |
||||
to a URL */ |
||||
node = mxmlFindElement(tree, tree, "a", |
||||
"href", |
||||
"http://www.example.com/", |
||||
MXML_DESCEND); |
||||
</pre> |
||||
<!-- NEED 5 --> |
||||
<pre> |
||||
/* Find the first element with a "src" |
||||
attribute */ |
||||
node = mxmlFindElement(tree, tree, NULL, |
||||
"src", NULL, |
||||
MXML_DESCEND); |
||||
</pre> |
||||
<!-- NEED 5 --> |
||||
<pre> |
||||
/* Find the first element with a "src" |
||||
= "foo.jpg" */ |
||||
node = mxmlFindElement(tree, tree, NULL, |
||||
"src", "foo.jpg", |
||||
MXML_DESCEND); |
||||
</pre> |
||||
|
||||
<p>You can also iterate with the same function:</p> |
||||
|
||||
<pre> |
||||
mxml_node_t *node; |
||||
|
||||
for (node = mxmlFindElement(tree, tree, |
||||
"name", |
||||
NULL, NULL, |
||||
MXML_DESCEND); |
||||
node != NULL; |
||||
node = mxmlFindElement(node, tree, |
||||
"name", |
||||
NULL, NULL, |
||||
MXML_DESCEND)) |
||||
{ |
||||
... do something ... |
||||
} |
||||
</pre> |
||||
|
||||
<!-- NEED 10 --> |
||||
<p>The <tt>MXML_DESCEND</tt> argument can actually be one of |
||||
three constants:</p> |
||||
|
||||
<ul> |
||||
|
||||
<li><tt>MXML_NO_DESCEND</tt> means to not to look at any |
||||
child nodes in the element hierarchy, just look at |
||||
siblings at the same level or parent nodes until the top |
||||
node or top-of-tree is reached. |
||||
|
||||
<p>The previous node from "group" would be the "node" |
||||
element to the left, while the next node from "group" would |
||||
be the "node" element to the right.<br><br></p></li> |
||||
|
||||
<li><tt>MXML_DESCEND_FIRST</tt> means that it is OK to |
||||
descend to the first child of a node, but not to descend |
||||
further when searching. You'll normally use this when |
||||
iterating through direct children of a parent node, e.g. all |
||||
of the "node" and "group" elements under the "?xml" parent |
||||
node in the example above. |
||||
|
||||
<p>This mode is only applicable to the search function; the |
||||
walk functions treat this as <tt>MXML_DESCEND</tt> since |
||||
every call is a first time.<br><br></p></li> |
||||
|
||||
<li><tt>MXML_DESCEND</tt> means to keep descending until |
||||
you hit the bottom of the tree. The previous node from |
||||
"group" would be the "val3" node and the next node would |
||||
be the first node element under "group". |
||||
|
||||
<p>If you were to walk from the root node "?xml" to the end |
||||
of the tree with <tt>mxmlWalkNext()</tt>, the order would |
||||
be:</p> |
||||
|
||||
<p><tt>?xml data node val1 node val2 node val3 group node |
||||
val4 node val5 node val6 node val7 node val8</tt></p> |
||||
|
||||
<p>If you started at "val8" and walked using |
||||
<tt>mxmlWalkPrev()</tt>, the order would be reversed, |
||||
ending at "?xml".</p></li> |
||||
|
||||
</ul> |
||||
|
||||
<h2>Finding Specific Nodes</h2> |
||||
|
||||
<p>You can find specific nodes in the tree using the <a |
||||
href='#mxmlFindValue'><tt>mxmlFindPath</tt></a>, for example: |
||||
|
||||
<pre> |
||||
mxml_node_t *value; |
||||
|
||||
value = mxmlFindPath(tree, "path/to/*/foo/bar"); |
||||
</pre> |
||||
|
||||
<p>The second argument is a "path" to the parent node. Each component of the |
||||
path is separated by a slash (/) and represents a named element in the document |
||||
tree or a wildcard (*) path representing 0 or more intervening nodes.</p> |
||||
|
||||
</body> |
||||
</html> |
@ -1,4 +1,4 @@ |
||||
.SH SEE ALSO |
||||
mxmldoc(1), Mini-XML Programmers Manual, https://michaelrsweet.github.io/mxml |
||||
Mini-XML Programmers Manual, https://www.msweet.org/mxml |
||||
.SH COPYRIGHT |
||||
Copyright \[co] 2003-2017 by Michael R Sweet. |
||||
Copyright \[co] 2003-2019 by Michael R Sweet. |
||||
|
Before Width: | Height: | Size: 31 KiB |
@ -1,77 +0,0 @@ |
||||
<html> |
||||
<body> |
||||
|
||||
<h1 align='right'><a name='INSTALL'>Chapter 1 - Building, |
||||
Installing, and Packaging Mini-XML</a></h1> |
||||
|
||||
<p>This chapter describes how to build, install, and package |
||||
Mini-XML on your system from the source archive. You will need an |
||||
ANSI/ISO-C compatible compiler to build Mini-XML - GCC works, as |
||||
do most vendors' C compilers. If you are building Mini-XML on |
||||
Windows, we recommend using the Visual C++ environment with the |
||||
supplied solution file. For other operating systems, you'll need a |
||||
POSIX-compatible shell and <tt>make</tt> program in addition to |
||||
the C compiler.</p> |
||||
|
||||
<h2>Compiling Mini-XML</h2> |
||||
|
||||
<p>Mini-XML comes with both an autoconf-based configure script |
||||
and a Visual C++ solution that can be used to compile the library |
||||
and associated tools.</p> |
||||
|
||||
<h3>Compiling with Visual C++</h3> |
||||
|
||||
<p>Open the <VAR>mxml.sln</VAR> solution in the <VAR>vcnet</VAR> |
||||
folder. Choose the desired build configuration, "Debug" (the |
||||
default) or "Release", and then choose <VAR>Build Solution</VAR> |
||||
from the <VAR>Build</VAR> menu.</p> |
||||
|
||||
<h3>Compiling with Command-Line Tools</h3> |
||||
|
||||
<p>Type the following command to configure the Mini-XML source |
||||
code for your system:</p> |
||||
|
||||
<pre> |
||||
<kbd>./configure ENTER</kbd> |
||||
</pre> |
||||
|
||||
<p>The default install prefix is <var>/usr/local</var>, which |
||||
can be overridden using the <kbd>--prefix</kbd> option:</p> |
||||
|
||||
<pre> |
||||
<kbd>./configure --prefix=/foo ENTER</kbd> |
||||
</pre> |
||||
|
||||
<p>Other configure options can be found using the |
||||
<kbd>--help</kbd> option:</p> |
||||
|
||||
<pre> |
||||
<kbd>./configure --help ENTER</kbd> |
||||
</pre> |
||||
|
||||
<p>Once you have configured the software, use the |
||||
<tt>make(1)</tt> program to do the build and run the test |
||||
program to verify that things are working, as follows:</p> |
||||
|
||||
<pre> |
||||
<kbd>make ENTER</kbd> |
||||
</pre> |
||||
|
||||
|
||||
<h2>Installing Mini-XML</h2> |
||||
|
||||
<p>If you are using Visual C++, copy the <VAR>mxml.lib</VAR> and |
||||
and <VAR>mxml.h</VAR> files to the Visual C++ <VAR>lib</VAR> and |
||||
<VAR>include<VAR> directories, respectively.</p> |
||||
|
||||
<p>Otherwise, use the <tt>make</tt> command with the |
||||
<kbd>install</kbd> target to install Mini-XML in the configured |
||||
directories:</p> |
||||
|
||||
<pre> |
||||
<kbd>make install ENTER</kbd> |
||||
</pre> |
||||
|
||||
|
||||
</body> |
||||
</html> |
@ -1,181 +0,0 @@ |
||||
<html> |
||||
<head> |
||||
<title>Mini-XML Programmers Manual, Version 2.12</title> |
||||
<meta name="copyright" content="Copyright 2003-2018"> |
||||
<meta name="author" content="Michael R Sweet"> |
||||
<meta name="keywords" content="XML, C, C++, library"> |
||||
</head> |
||||
<body> |
||||
|
||||
<h1 align="right"><a name="INTRO">Introduction</a></h1> |
||||
|
||||
<p>This programmers manual describes Mini-XML version 2.12, a small |
||||
XML parsing library that you can use to read and write XML data |
||||
files in your C and C++ applications.</p> |
||||
|
||||
<p>Mini-XML was initially developed for the <a |
||||
href="http://gutenprint.sf.net/">Gutenprint</a> project to replace |
||||
the rather large and unwieldy <tt>libxml2</tt> library with |
||||
something substantially smaller and easier-to-use. It all began one |
||||
morning in June of 2003 when Robert posted the following sentence to |
||||
the developer's list:</p> |
||||
|
||||
<blockquote><em>It's bad enough that we require libxml2, but rolling |
||||
our own XML parser is a bit more than we can handle.</em></blockquote> |
||||
|
||||
<p>I then replied with:</p> |
||||
|
||||
<blockquote><em>Given the limited scope of what you use in XML, it |
||||
should be trivial to code a mini-XML API in a few hundred lines of |
||||
code.</em></blockquote> |
||||
|
||||
<p>I took my own challenge and coded furiously for two days to |
||||
produced the initial public release of Mini-XML, total lines of |
||||
code: 696. Robert promptly integrated Mini-XML into Gutenprint |
||||
and removed libxml2.</p> |
||||
|
||||
<p>Thanks to lots of feedback and support from various |
||||
developers, Mini-XML has evolved since then to provide a more |
||||
complete XML implementation and now stands at a whopping 3,792 |
||||
lines of code, compared to 140,410 lines of code for libxml2 |
||||
version 2.9.1.</p> |
||||
|
||||
<p>Aside from Gutenprint, Mini-XML is used for the |
||||
following projects/software applications:</p> |
||||
|
||||
<ul> |
||||
|
||||
<li><a href="https://www.cups.org/">CUPS</a></li> |
||||
|
||||
<li><a |
||||
href="http://zynaddsubfx.sourceforge.net">ZynAddSubFX</a></li> |
||||
|
||||
</ul> |
||||
|
||||
<p>Please file a bug on Github if you would like your project added or |
||||
removed from this list, or if you have any comments/quotes you would like me to |
||||
publish about your experiences with Mini-XML.</p> |
||||
|
||||
<!-- NEED 1in --> |
||||
<h2>Organization of This Document</h2> |
||||
|
||||
<p>This manual is organized into the following chapters and |
||||
appendices:</p> |
||||
|
||||
<ul> |
||||
|
||||
<li>Chapter 1, "<a href="#INSTALL">Building, |
||||
Installing, and Packaging Mini-XML</a>", provides |
||||
compilation, installation, and packaging instructions for |
||||
Mini-XML.</li> |
||||
|
||||
<li>Chapter 2, "<a href="#BASICS">Getting |
||||
Started with Mini-XML</a>", shows how to use the |
||||
Mini-XML library in your programs.</li> |
||||
|
||||
<li>Chapter 3, "<a href="#ADVANCED">More |
||||
Mini-XML Programming Techniques</a>", shows additional |
||||
ways to use the Mini-XML library.</li> |
||||
|
||||
<li>Appendix A, "<a href="#LICENSE">Mini-XML License</a>", |
||||
provides the terms and conditions for using and distributing |
||||
Mini-XML.</li> |
||||
|
||||
<li>Appendix B, "<a href="#REFERENCE">Library |
||||
Reference</a>", contains a complete reference for |
||||
Mini-XML, generated by <tt>mxmldoc</tt>.</li> |
||||
|
||||
</ul> |
||||
|
||||
<!-- NEED 10 --> |
||||
<h2>Notation Conventions</h2> |
||||
|
||||
<p>Various font and syntax conventions are used in this guide. |
||||
Examples and their meanings and uses are explained below:</p> |
||||
|
||||
<dl> |
||||
|
||||
<dt><code>mxmldoc</code><br> |
||||
<code>mxmldoc(1)</code></dt> |
||||
|
||||
<dd>The names of commands; the first mention of a command |
||||
or function in a chapter is followed by a manual page |
||||
section number.<br><br></dd> |
||||
|
||||
<dt><var>/var</var><br> |
||||
<var>/etc/hosts</var></dt> |
||||
|
||||
<dd>File and directory names.<br><br></dd> |
||||
|
||||
<dt><tt>Request ID is Printer-123</tt></dt> |
||||
|
||||
<dd>Screen output.<br><br></dd> |
||||
|
||||
<dt><kbd>lp -d printer filename ENTER</kbd></dt> |
||||
|
||||
<dd>Literal user input; special keys like |
||||
<kbd>ENTER</kbd> are in ALL CAPS.<br><br></dd> |
||||
|
||||
<dt>12.3</dt> |
||||
|
||||
<dd>Numbers in the text are written using the period (.) |
||||
to indicate the decimal point.<br><br></dd> |
||||
|
||||
</dl> |
||||
|
||||
<!-- NEED 10 --> |
||||
<h2>Abbreviations</h2> |
||||
|
||||
<p>The following abbreviations are used throughout this |
||||
manual:</p> |
||||
|
||||
<dl> |
||||
|
||||
<dt>Gb</dt> |
||||
<dd>Gigabytes, or 1073741824 bytes<br><br></dd> |
||||
|
||||
<dt>kb</dt> |
||||
<dd>Kilobytes, or 1024 bytes<br><br></dd> |
||||
|
||||
<dt>Mb</dt> |
||||
<dd>Megabytes, or 1048576 bytes<br><br></dd> |
||||
|
||||
<dt>UTF-8, UTF-16</dt> |
||||
<dd>Unicode Transformation Format, 8-bit or 16-bit<br><br></dd> |
||||
|
||||
<dt>W3C</dt> |
||||
<dd>World Wide Web Consortium<br><br></dd> |
||||
|
||||
<dt>XML</dt> |
||||
<dd>Extensible Markup Language<br><br></dd> |
||||
|
||||
</dl> |
||||
|
||||
<!-- NEED 12 --> |
||||
<h2>Other References</h2> |
||||
|
||||
<dl> |
||||
|
||||
<dt>The Unicode Standard, Version 4.0, Addison-Wesley, |
||||
ISBN 0-321-18578-1</dt> |
||||
|
||||
<dd>The definition of the Unicode character set which is |
||||
used for XML.<br><br></dd> |
||||
|
||||
<dt><a |
||||
href="http://www.w3.org/TR/2004/REC-xml-20040204/">Extensible |
||||
Markup Language (XML) 1.0 (Third Edition)</a></dt> |
||||
|
||||
<dd>The XML specification from the World Wide Web |
||||
Consortium (W3C)<br><br></dd> |
||||
|
||||
</dl> |
||||
|
||||
<!-- NEED 6 --> |
||||
<h2>Legal Stuff</h2> |
||||
|
||||
<p>The Mini-XML library is copyright 2003-2018 by Michael R Sweet. License terms |
||||
are described in <a href="#LICENSE">Appendix A - Mini-XML License</a>.</p> |
||||
|
||||
</body> |
||||
</html> |
@ -1,593 +0,0 @@ |
||||
<html> |
||||
<body> |
||||
|
||||
<h1 align='right'><a name='LICENSE'>Appendix A - Mini-XML |
||||
License</a></h1> |
||||
|
||||
<p>The Mini-XML library and included programs are provided under |
||||
the terms of the GNU Library General Public License version 2 |
||||
(LGPL2) with the following exceptions:</p> |
||||
|
||||
<p><b>1.</b> Static linking of applications to the Mini-XML |
||||
library does not constitute a derivative work and does |
||||
not require the author to provide source code for the |
||||
application, use the shared Mini-XML libraries, or link |
||||
their applications against a user-supplied version of |
||||
Mini-XML.</p> |
||||
|
||||
<p><i>If you link the application to a modified version |
||||
of Mini-XML, then the changes to Mini-XML must be |
||||
provided under the terms of the LGPL2 in sections 1, 2, |
||||
and 4.</i></p> |
||||
|
||||
<p><b>2.</b> You do not have to provide a copy of the Mini-XML |
||||
license with programs that are linked to the Mini-XML |
||||
library, nor do you have to identify the Mini-XML license |
||||
in your program or documentation as required by section 6 |
||||
of the LGPL2.</p> |
||||
|
||||
<p> </p> |
||||
|
||||
<p align=center><b>GNU LIBRARY GENERAL PUBLIC LICENSE</b></p> |
||||
<p align='center'>Version 2, June 1991 |
||||
<br>Copyright (C) 1991 Free Software Foundation, Inc. |
||||
<br>59 Temple Place - Suite 330, Boston, MA 02111-1307, USA |
||||
<br>Everyone is permitted to copy and distribute verbatim copies of |
||||
this license document, but changing it is not allowed. |
||||
<br>[This is the first released version of the library GPL. It is |
||||
numbered 2 because it goes with version 2 of the ordinary GPL.]</p> |
||||
|
||||
<p><b>Preamble</b></p> |
||||
|
||||
<p>The licenses for most software are designed to take away your freedom |
||||
to share and change it. By contrast, the GNU General Public Licenses |
||||
are intended to guarantee your freedom to share and change free |
||||
software--to make sure the software is free for all its users.</p> |
||||
|
||||
<p>This license, the Library General Public License, applies to some |
||||
specially designated Free Software Foundation software, and to any |
||||
other libraries whose authors decide to use it. You can use it for |
||||
your libraries, too.</p> |
||||
|
||||
<p>When we speak of free software, we are referring to freedom, |
||||
not price. Our General Public Licenses are designed to make sure |
||||
that you have the freedom to distribute copies of free software |
||||
(and charge for this service if you wish), that you receive |
||||
source code or can get it if you want it, that you can change |
||||
the software or use pieces of it in new free programs; and that |
||||
you know you can do these things.</p> |
||||
|
||||
<p>To protect your rights, we need to make restrictions that |
||||
forbid anyone to deny you these rights or to ask you to |
||||
surrender the rights. These restrictions translate to certain |
||||
responsibilities for you if you distribute copies of the |
||||
library, or if you modify it.</p> |
||||
|
||||
<p>For example, if you distribute copies of the library, whether |
||||
gratis or for a fee, you must give the recipients all the rights |
||||
that we gave you. You must make sure that they, too, receive or |
||||
can get the source code. If you link a program with the library, |
||||
you must provide complete object files to the recipients so that |
||||
they can relink them with the library, after making changes to |
||||
the library and recompiling it. And you must show them these |
||||
terms so they know their rights.</p> |
||||
|
||||
<p>Our method of protecting your rights has two steps: (1) |
||||
copyright the library, and (2) offer you this license which |
||||
gives you legal permission to copy, distribute and/or modify the |
||||
library.</p> |
||||
|
||||
<p>Also, for each distributor's protection, we want to make |
||||
certain that everyone understands that there is no warranty for |
||||
this free library. If the library is modified by someone else |
||||
and passed on, we want its recipients to know that what they |
||||
have is not the original version, so that any problems |
||||
introduced by others will not reflect on the original authors' |
||||
reputations.</p> |
||||
|
||||
<p>Finally, any free program is threatened constantly by |
||||
software patents. We wish to avoid the danger that companies |
||||
distributing free software will individually obtain patent |
||||
licenses, thus in effect transforming the program into |
||||
proprietary software. To prevent this, we have made it clear |
||||
that any patent must be licensed for everyone's free use or not |
||||
licensed at all.</p> |
||||
|
||||
<p>Most GNU software, including some libraries, is covered by |
||||
the ordinary GNU General Public License, which was designed for |
||||
utility programs. This license, the GNU Library General Public |
||||
License, applies to certain designated libraries. This license |
||||
is quite different from the ordinary one; be sure to read it in |
||||
full, and don't assume that anything in it is the same as in the |
||||
ordinary license.</p> |
||||
|
||||
<p>The reason we have a separate public license for some |
||||
libraries is that they blur the distinction we usually make |
||||
between modifying or adding to a program and simply using it. |
||||
Linking a program with a library, without changing the library, |
||||
is in some sense simply using the library, and is analogous to |
||||
running a utility program or application program. However, in a |
||||
textual and legal sense, the linked executable is a combined |
||||
work, a derivative of the original library, and the ordinary |
||||
General Public License treats it as such.</p> |
||||
|
||||
<p>Because of this blurred distinction, using the ordinary |
||||
General Public License for libraries did not effectively promote |
||||
software sharing, because most developers did not use the |
||||
libraries. We concluded that weaker conditions might promote |
||||
sharing better.</p> |
||||
|
||||
<p>However, unrestricted linking of non-free programs would |
||||
deprive the users of those programs of all benefit from the free |
||||
status of the libraries themselves. This Library General Public |
||||
License is intended to permit developers of non-free programs to |
||||
use free libraries, while preserving your freedom as a user of |
||||
such programs to change the free libraries that are incorporated |
||||
in them. (We have not seen how to achieve this as regards |
||||
changes in header files, but we have achieved it as regards |
||||
changes in the actual functions of the Library.) The hope is |
||||
that this will lead to faster development of free libraries.</p> |
||||
|
||||
<p>The precise terms and conditions for copying, distribution |
||||
and modification follow. Pay close attention to the difference |
||||
between a "work based on the libary" and a "work |
||||
that uses the library". The former contains code derived |
||||
from the library, while the latter only works together with the |
||||
library.</p> |
||||
|
||||
<p>Note that it is possible for a library to be covered by the |
||||
ordinary General Public License rather than by this special |
||||
one.</p> |
||||
|
||||
<p align='center'><b>TERMS AND CONDITIONS FOR COPYING, |
||||
DISTRIBUTION AND MODIFICATION</b></p> |
||||
|
||||
<p><strong>0.</strong> This License Agreement applies to any |
||||
software library which contains a notice placed by the copyright |
||||
holder or other authorized party saying it may be distributed |
||||
under the terms of this Library General Public License (also |
||||
called "this License"). Each licensee is addressed as |
||||
"you". |
||||
|
||||
<p>A "library" means a collection of software |
||||
functions and/or data prepared so as to be conveniently linked |
||||
with application programs (which use some of those functions and |
||||
data) to form executables.</p> |
||||
|
||||
<p>The "Library", below, refers to any such software |
||||
library or work which has been distributed under these terms. A |
||||
"work based on the Library" means either the Library |
||||
or any derivative work under copyright law: that is to say, a |
||||
work containing the Library or a portion of it, either verbatim |
||||
or with modifications and/or translated straightforwardly into |
||||
another language. (Hereinafter, translation is included without |
||||
limitation in the term "modification".)</p> |
||||
|
||||
<p>"Source code" for a work means the preferred form |
||||
of the work for making modifications to it. For a library, |
||||
complete source code means all the source code for all modules |
||||
it contains, plus any associated interface definition files, |
||||
plus the scripts used to control compilation and installation of |
||||
the library.</p> |
||||
|
||||
<p>Activities other than copying, distribution and modification |
||||
are not covered by this License; they are outside its scope. The |
||||
act of running a program using the Library is not restricted, |
||||
and output from such a program is covered only if its contents |
||||
constitute a work based on the Library (independent of the use |
||||
of the Library in a tool for writing it). Whether that is true |
||||
depends on what the Library does and what the program that uses |
||||
the Library does.</p> |
||||
|
||||
<p><strong>1.</strong> You may copy and distribute verbatim |
||||
copies of the Library's complete source code as you receive it, |
||||
in any medium, provided that you conspicuously and appropriately |
||||
publish on each copy an appropriate copyright notice and |
||||
disclaimer of warranty; keep intact all the notices that refer |
||||
to this License and to the absence of any warranty; and |
||||
distribute a copy of this License along with the Library.</p> |
||||
|
||||
<p>You may charge a fee for the physical act of transferring a |
||||
copy, and you may at your option offer warranty protection in |
||||
exchange for a fee.</p> |
||||
|
||||
<p><strong>2.</strong> You may modify your copy or copies of the |
||||
Library or any portion of it, thus forming a work based on the |
||||
Library, and copy and distribute such modifications or work |
||||
under the terms of Section 1 above, provided that you also meet |
||||
all of these conditions:</p> |
||||
|
||||
<ul> |
||||
|
||||
<p><strong>a)</strong> The modified work must itself be |
||||
a software library. |
||||
|
||||
<p><strong>b)</strong> You must cause the files modified |
||||
to carry prominent notices stating that you changed the |
||||
files and the date of any change.</p> |
||||
|
||||
<p><strong>c)</strong> You must cause the whole of the |
||||
work to be licensed at no charge to all third parties |
||||
under the terms of this License.</p> |
||||
|
||||
<p><strong>d)</strong> If a facility in the modified |
||||
Library refers to a function or a table of data to be |
||||
supplied by an application program that uses the |
||||
facility, other than as an argument passed when the |
||||
facility is invoked, then you must make a good faith |
||||
effort to ensure that, in the event an application does |
||||
not supply such function or table, the facility still |
||||
operates, and performs whatever part of its purpose |
||||
remains meaningful.</p> |
||||
|
||||
<p>(For example, a function in a library to compute |
||||
square roots has a purpose that is entirely well-defined |
||||
independent of the application. Therefore, Subsection 2d |
||||
requires that any application-supplied function or table |
||||
used by this function must be optional: if the |
||||
application does not supply it, the square root function |
||||
must still compute square roots.)</p> |
||||
|
||||
</ul> |
||||
|
||||
<p>These requirements apply to the modified work as a whole. If |
||||
identifiable sections of that work are not derived from the |
||||
Library, and can be reasonably considered independent and |
||||
separate works in themselves, then this License, and its terms, |
||||
do not apply to those sections when you distribute them as |
||||
separate works. But when you distribute the same sections as |
||||
part of a whole which is a work based on the Library, the |
||||
distribution of the whole must be on the terms of this License, |
||||
whose permissions for other licensees extend to the entire |
||||
whole, and thus to each and every part regardless of who wrote |
||||
it.</p> |
||||
|
||||
<p>Thus, it is not the intent of this section to claim rights or |
||||
contest your rights to work written entirely by you; rather, the |
||||
intent is to exercise the right to control the distribution of |
||||
derivative or collective works based on the Library.</p> |
||||
|
||||
<p>In addition, mere aggregation of another work not based on |
||||
the Library with the Library (or with a work based on the |
||||
Library) on a volume of a storage or distribution medium does |
||||
not bring the other work under the scope of this License.</p> |
||||
|
||||
<p><strong>3.</strong> You may opt to apply the terms of the |
||||
ordinary GNU General Public License instead of this License to a |
||||
given copy of the Library. To do this, you must alter all the |
||||
notices that refer to this License, so that they refer to the |
||||
ordinary GNU General Public License, version 2, instead of to |
||||
this License. (If a newer version than version 2 of the ordinary |
||||
GNU General Public License has appeared, then you can specify |
||||
that version instead if you wish.) Do not make any other change |
||||
in these notices.</p> |
||||
|
||||
<p>Once this change is made in a given copy, it is irreversible |
||||
for that copy, so the ordinary GNU General Public License |
||||
applies to all subsequent copies and derivative works made from |
||||
that copy.</p> |
||||
|
||||
<p>This option is useful when you wish to copy part of the code |
||||
of the Library into a program that is not a library.</p> |
||||
|
||||
<p><strong>4.</strong> You may copy and distribute the Library |
||||
(or a portion or derivative of it, under Section 2) in object |
||||
code or executable form under the terms of Sections 1 and 2 |
||||
above provided that you accompany it with the complete |
||||
corresponding machine-readable source code, which must be |
||||
distributed under the terms of Sections 1 and 2 above on a |
||||
medium customarily used for software interchange.</p> |
||||
|
||||
<p>If distribution of object code is made by offering access to |
||||
copy from a designated place, then offering equivalent access to |
||||
copy the source code from the same place satisfies the |
||||
requirement to distribute the source code, even though third |
||||
parties are not compelled to copy the source along with the |
||||
object code.</p> |
||||
|
||||
<p><strong>5.</strong> A program that contains no derivative of |
||||
any portion of the Library, but is designed to work with the |
||||
Library by being compiled or linked with it, is called a |
||||
"work that uses the Library". Such a work, in |
||||
isolation, is not a derivative work of the Library, and |
||||
therefore falls outside the scope of this License.</p> |
||||
|
||||
<p>However, linking a "work that uses the Library" |
||||
with the Library creates an executable that is a derivative of |
||||
the Library (because it contains portions of the Library), |
||||
rather than a "work that uses the library". The |
||||
executable is therefore covered by this License. Section 6 |
||||
states terms for distribution of such executables.</p> |
||||
|
||||
<p>When a "work that uses the Library" uses material |
||||
from a header file that is part of the Library, the object code |
||||
for the work may be a derivative work of the Library even though |
||||
the source code is not. Whether this is true is especially |
||||
significant if the work can be linked without the Library, or if |
||||
the work is itself a library. The threshold for this to be true |
||||
is not precisely defined by law.</p> |
||||
|
||||
<p>If such an object file uses only numerical parameters, data |
||||
structure layouts and accessors, and small macros and small |
||||
inline functions (ten lines or less in length), then the use of |
||||
the object file is unrestricted, regardless of whether it is |
||||
legally a derivative work. (Executables containing this object |
||||
code plus portions of the Library will still fall under Section |
||||
6.)</p> |
||||
|
||||
<p>Otherwise, if the work is a derivative of the Library, you |
||||
may distribute the object code for the work under the terms of |
||||
Section 6. Any executables containing that work also fall under |
||||
Section 6, whether or not they are linked directly with the |
||||
Library itself.</p> |
||||
|
||||
<p><strong>6.</strong> As an exception to the Sections above, |
||||
you may also compile or link a "work that uses the |
||||
Library" with the Library to produce a work containing |
||||
portions of the Library, and distribute that work under terms of |
||||
your choice, provided that the terms permit modification of the |
||||
work for the customer's own use and reverse engineering for |
||||
debugging such modifications.</p> |
||||
|
||||
<p>You must give prominent notice with each copy of the work |
||||
that the Library is used in it and that the Library and its use |
||||
are covered by this License. You must supply a copy of this |
||||
License. If the work during execution displays copyright |
||||
notices, you must include the copyright notice for the Library |
||||
among them, as well as a reference directing the user to the |
||||
copy of this License. Also, you must do one of these things:</p> |
||||
|
||||
<ul> |
||||
|
||||
<strong>a)</strong> Accompany the work with the complete |
||||
corresponding machine-readable source code for the |
||||
Library including whatever changes were used in the work |
||||
(which must be distributed under Sections 1 and 2 |
||||
above); and, if the work is an executable linked with |
||||
the Library, with the complete machine-readable |
||||
"work that uses the Library", as object code |
||||
and/or source code, so that the user can modify the |
||||
Library and then relink to produce a modified executable |
||||
containing the modified Library. (It is understood that |
||||
the user who changes the contents of definitions files |
||||
in the Library will not necessarily be able to recompile |
||||
the application to use the modified definitions.) |
||||
|
||||
<p><strong>b)</strong> Accompany the work with a written |
||||
offer, valid for at least three years, to give the same |
||||
user the materials specified in Subsection 6a, above, |
||||
for a charge no more than the cost of performing this |
||||
distribution.</p> |
||||
|
||||
<p><strong>c)</strong> If distribution of the work is |
||||
made by offering access to copy from a designated place, |
||||
offer equivalent access to copy the above specified |
||||
materials from the same place.</p> |
||||
|
||||
<p><strong>d)</strong> Verify that the user has already |
||||
received a copy of these materials or that you have |
||||
already sent this user a copy.</p> |
||||
|
||||
</ul> |
||||
|
||||
<p>For an executable, the required form of the "work that |
||||
uses the Library" must include any data and utility |
||||
programs needed for reproducing the executable from it. However, |
||||
as a special exception, the source code distributed need not |
||||
include anything that is normally distributed (in either source |
||||
or binary form) with the major components (compiler, kernel, and |
||||
so on) of the operating system on which the executable runs, |
||||
unless that component itself accompanies the executable.</p> |
||||
|
||||
<p>It may happen that this requirement contradicts the license |
||||
restrictions of other proprietary libraries that do not normally |
||||
accompany the operating system. Such a contradiction means you |
||||
cannot use both them and the Library together in an executable |
||||
that you distribute.</p> |
||||
|
||||
<p><strong>7.</strong> You may place library facilities that are |
||||
a work based on the Library side-by-side in a single library |
||||
together with other library facilities not covered by this |
||||
License, and distribute such a combined library, provided that |
||||
the separate distribution of the work based on the Library and |
||||
of the other library facilities is otherwise permitted, and |
||||
provided that you do these two things:</p> |
||||
|
||||
<ul> |
||||
|
||||
<strong>a)</strong> Accompany the combined library with |
||||
a copy of the same work based on the Library, uncombined |
||||
with any other library facilities. This must be |
||||
distributed under the terms of the Sections above. |
||||
|
||||
<p><strong>b)</strong> Give prominent notice with the |
||||
combined library of the fact that part of it is a work |
||||
based on the Library, and explaining where to find the |
||||
accompanying uncombined form of the same work.</p> |
||||
|
||||
</ul> |
||||
|
||||
<p><strong>8.</strong> You may not copy, modify, sublicense, |
||||
link with, or distribute the Library except as expressly |
||||
provided under this License. Any attempt otherwise to copy, |
||||
modify, sublicense, link with, or distribute the Library is |
||||
void, and will automatically terminate your rights under this |
||||
License. However, parties who have received copies, or rights, |
||||
from you under this License will not have their licenses |
||||
terminated so long as such parties remain in full |
||||
compliance.</p> |
||||
|
||||
<p><strong>9.</strong> You are not required to accept this |
||||
License, since you have not signed it. However, nothing else |
||||
grants you permission to modify or distribute the Library or its |
||||
derivative works. These actions are prohibited by law if you do |
||||
not accept this License. Therefore, by modifying or distributing |
||||
the Library (or any work based on the Library), you indicate |
||||
your acceptance of this License to do so, and all its terms and |
||||
conditions for copying, distributing or modifying the Library or |
||||
works based on it.</p> |
||||
|
||||
<p><strong>10.</strong> Each time you redistribute the Library |
||||
(or any work based on the Library), the recipient automatically |
||||
receives a license from the original licensor to copy, |
||||
distribute, link with or modify the Library subject to these |
||||
terms and conditions. You may not impose any further |
||||
restrictions on the recipients' exercise of the rights granted |
||||
herein. You are not responsible for enforcing compliance by |
||||
third parties to this License.</p> |
||||
|
||||
<p><strong>11.</strong> If, as a consequence of a court judgment |
||||
or allegation of patent infringement or for any other reason |
||||
(not limited to patent issues), conditions are imposed on you |
||||
(whether by court order, agreement or otherwise) that contradict |
||||
the conditions of this License, they do not excuse you from the |
||||
conditions of this License. If you cannot distribute so as to |
||||
satisfy simultaneously your obligations under this License and |
||||
any other pertinent obligations, then as a consequence you may |
||||
not distribute the Library at all. For example, if a patent |
||||
license would not permit royalty-free redistribution of the |
||||
Library by all those who receive copies directly or indirectly |
||||
through you, then the only way you could satisfy both it and |
||||
this License would be to refrain entirely from distribution of |
||||
the Library.</p> |
||||
|
||||
<p>If any portion of this section is held invalid or |
||||
unenforceable under any particular circumstance, the balance of |
||||
the section is intended to apply, and the section as a whole is |
||||
intended to apply in other circumstances.</p> |
||||
|
||||
<p>It is not the purpose of this section to induce you to |
||||
infringe any patents or other property right claims or to |
||||
contest validity of any such claims; this section has the sole |
||||
purpose of protecting the integrity of the free software |
||||
distribution system which is implemented by public license |
||||
practices. Many people have made generous contributions to the |
||||
wide range of software distributed through that system in |
||||
reliance on consistent application of that system; it is up to |
||||
the author/donor to decide if he or she is willing to distribute |
||||
software through any other system and a licensee cannot impose |
||||
that choice.</p> |
||||
|
||||
<p>This section is intended to make thoroughly clear what is |
||||
believed to be a consequence of the rest of this License.</p> |
||||
|
||||
<p><strong>12.</strong> If the distribution and/or use of the |
||||
Library is restricted in certain countries either by patents or |
||||
by copyrighted interfaces, the original copyright holder who |
||||
places the Library under this License may add an explicit |
||||
geographical distribution limitation excluding those countries, |
||||
so that distribution is permitted only in or among countries not |
||||
thus excluded. In such case, this License incorporates the |
||||
limitation as if written in the body of this License.</p> |
||||
|
||||
<p><strong>13.</strong> The Free Software Foundation may publish |
||||
revised and/or new versions of the Library General Public |
||||
License from time to time. Such new versions will be similar in |
||||
spirit to the present version, but may differ in detail to |
||||
address new problems or concerns.</p> |
||||
|
||||
<p>Each version is given a distinguishing version number. If the |
||||
Library specifies a version number of this License which applies |
||||
to it and "any later version", you have the option of |
||||
following the terms and conditions either of that version or of |
||||
any later version published by the Free Software Foundation. If |
||||
the Library does not specify a license version number, you may |
||||
choose any version ever published by the Free Software |
||||
Foundation.</p> |
||||
|
||||
<p><strong>14.</strong> If you wish to incorporate parts of the |
||||
Library into other free programs whose distribution conditions |
||||
are incompatible with these, write to the author to ask for |
||||
permission. For software which is copyrighted by the Free |
||||
Software Foundation, write to the Free Software Foundation; we |
||||
sometimes make exceptions for this. Our decision will be guided |
||||
by the two goals of preserving the free status of all |
||||
derivatives of our free software and of promoting the sharing |
||||
and reuse of software generally.</p> |
||||
|
||||
<p align='center'><b>NO WARRANTY</b></p> |
||||
|
||||
<p><strong>15.</strong> BECAUSE THE LIBRARY IS LICENSED FREE OF |
||||
CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT |
||||
PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN |
||||
WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE |
||||
LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER |
||||
EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF |
||||
THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU |
||||
ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR |
||||
CORRECTION.</p> |
||||
|
||||
<p><strong>16.</strong> IN NO EVENT UNLESS REQUIRED BY |
||||
APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT |
||||
HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE |
||||
THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, |
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL |
||||
DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY |
||||
(INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING |
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES |
||||
OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), |
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE |
||||
POSSIBILITY OF SUCH DAMAGES.</p> |
||||
|
||||
<p align='center'><b>END OF TERMS AND CONDITIONS</b></p> |
||||
|
||||
<p><b>How to Apply These Terms to Your New Libraries</b></p> |
||||
|
||||
<p>If you develop a new library, and you want it to be of the |
||||
greatest possible use to the public, we recommend making it free |
||||
software that everyone can redistribute and change. You can do so |
||||
by permitting redistribution under these terms (or, alternatively, |
||||
under the terms of the ordinary General Public License). |
||||
|
||||
<p>To apply these terms, attach the following notices to the |
||||
library. It is safest to attach them to the start of each source |
||||
file to most effectively convey the exclusion of warranty; and each |
||||
file should have at least the "copyright" line and a pointer to |
||||
where the full notice is found. |
||||
|
||||
<ul> |
||||
|
||||
<p><var>one line to give the library's name and an idea of what it |
||||
does.</var><br> |
||||
Copyright (C) <var>year</var> <var>name of author</var> |
||||
|
||||
<p>This library is free software; you can redistribute it and/or |
||||
modify it under the terms of the GNU Lesser General Public License |
||||
as published by the Free Software Foundation; either version 2.1 of |
||||
the License, or (at your option) any later version. |
||||
|
||||
<p>This library 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 |
||||
Lesser General Public License for more details. |
||||
|
||||
<p>You should have received a copy of the GNU Lesser General Public |
||||
License along with this library; if not, write to the Free Software |
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
||||
02111-1307 USA |
||||
|
||||
</ul> |
||||
|
||||
<p>Also add information on how to contact you by electronic and paper mail. |
||||
|
||||
<p>You should also get your employer (if you work as a programmer) |
||||
or your school, if any, to sign a "copyright disclaimer" for the |
||||
library, if necessary. Here is a sample; alter the names: |
||||
|
||||
<ul> |
||||
|
||||
<p>Yoyodyne, Inc., hereby disclaims all copyright interest in the |
||||
library `Frob' (a library for tweaking knobs) written by James |
||||
Random Hacker. |
||||
|
||||
<p><var>signature of Ty Coon</var>, 1 April 1990 Ty Coon, President |
||||
of Vice |
||||
|
||||
</ul> |
||||
|
||||
<p>That's all there is to it! |
||||
|
||||
</body> |
||||
</html> |
@ -1,24 +0,0 @@ |
||||
#!/bin/sh |
||||
# |
||||
# Script to make documentation... |
||||
# |
||||
# Copyright 2003-2017 by Michael R Sweet. |
||||
# |
||||
# These coded instructions, statements, and computer programs are the |
||||
# property of Michael R Sweet and are protected by Federal copyright |
||||
# law. Distribution and use rights are outlined in the file "COPYING" |
||||
# which should have been included with this file. If this file is |
||||
# missing or damaged, see the license at: |
||||
# |
||||
# https://michaelrsweet.github.io/mxml |
||||
# |
||||
|
||||
htmldoc --verbose --path "hires;." --batch mxml.book -f mxml.pdf |
||||
|
||||
htmldoc --verbose --batch mxml.book --no-title -f mxml.html |
||||
|
||||
htmldoc --verbose --batch mxml.book --titleimage mxml-cover.png -f mxml.epub |
||||
|
||||
rm -rf mxml.d |
||||
mkdir mxml.d |
||||
htmldoc --verbose --batch mxml.book --no-title -t html -d mxml.d |
@ -1,8 +0,0 @@ |
||||
#HTMLDOC 1.8.30 |
||||
-t pdf14 -f "mxml.pdf" --book --toclevels 3 --no-numbered --toctitle "Table of Contents" --title --titleimage "title.html" --linkstyle plain --size 4.25x6.875in --left 0.750in --right 0.50in --top 0.50in --bottom 0.50in --header .t. --header1 ... --footer h.1 --nup 1 --tocheader .t. --tocfooter ..i --duplex --portrait --color --no-pscommands --no-xrxcomments --compression=9 --jpeg=95 --fontsize 9.0 --fontspacing 1.2 --headingfont Helvetica --bodyfont Helvetica --headfootsize 8.0 --headfootfont Helvetica-Oblique --charset iso-8859-1 --links --embedfonts --pagemode outline --pagelayout single --firstpage c1 --pageeffect none --pageduration 10 --effectduration 1.0 --no-encryption --permissions all --owner-password "" --user-password "" --browserwidth 300 --no-strict --no-overflow |
||||
intro.html |
||||
install.html |
||||
basics.html |
||||
advanced.html |
||||
license.html |
||||
reference.html |
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -1 +0,0 @@ |
||||
<h1 align="right"><a name="REFERENCE">Appendix B - Library Reference</a></h1> |
File diff suppressed because it is too large
Load Diff
@ -1,33 +0,0 @@ |
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> |
||||
<html> |
||||
<head> |
||||
<title>Mini-XML Programmers Manual</title> |
||||
<meta name="author" content="Michael R Sweet"> |
||||
<meta name="copyright" content="Copyright 2003-2018"> |
||||
</head> |
||||
<body> |
||||
|
||||
<table width="100%" height="100%" border="0" cellpadding="0" cellspacing="0" summary=""> |
||||
<tr><td height="100%"> |
||||
|
||||
<h1 align="center"><img src="mxml.png" width="50%"><br> |
||||
<font size="-1">Mini-XML Programmers Manual<br> |
||||
Version 2.12</h1> |
||||
|
||||
<P ALIGN="CENTER">MICHAEL R. SWEET</P> |
||||
|
||||
</td></tr> |
||||
</table> |
||||
|
||||
<!-- NEW PAGE --> |
||||
<P><FONT SIZE="+1"><B>Mini-XML Programmers Manual, Version 2.12</B></FONT></P> |
||||
|
||||
<P><B>Copyright © 2003-2018 by Michael R Sweet</B></P> |
||||
|
||||
<P><SMALL>Permission is granted to copy, distribute and/or modify |
||||
this document under the terms of the GNU Library General Public |
||||
License, Version 2. A copy of this license is included in <A |
||||
HREF="#LICENSE">Appendix A - Mini-XML License</A>.</SMALL></P> |
||||
|
||||
</body> |
||||
</html> |
Loading…
Reference in new issue