Skip to content

Commit

Permalink
Save work on docos.
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelrsweet committed Mar 10, 2024
1 parent 9e22b3e commit a9aea16
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 98 deletions.
84 changes: 44 additions & 40 deletions doc/body.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,13 @@ I then replied with:
> 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.

I took my own challenge and coded furiously for two days to produced the initial
I took my own challenge and coded furiously for two days to produce the initial
public release of Mini-XML, total lines of code: 696. Robert promptly
integrated Mini-XML into Gutenprint and removed libxml2.

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,839 lines of code, compared to 175,808 lines of code for libxml2
at a whopping 3,875 lines of code, compared to 175,808 lines of code for libxml2
version 2.11.7.


Expand All @@ -62,6 +62,9 @@ The Mini-XML home page can be found at <https://www.msweet.org/mxml>. From
there you can download the current version of Mini-XML, access the issue
tracker, and find other resources.

Mini-XML v4 has a slightly different API than prior releases. See the
[Migrating from Mini-XML v3.x](@) chapter for details.


Legal Stuff
-----------
Expand Down Expand Up @@ -90,17 +93,20 @@ proper compiler and linker options for your installation:

gcc `pkg-config --cflags mxml4` -o myprogram myprogram.c `pkg-config --libs mxml4`

> Note: The library name "mxml4" is a configure-time option. If you use the
> `--disable-libmxml4-prefix` configure option the library is named "mxml".


Loading an XML File
-------------------

You load an XML file using the `mxmlLoadFile` function:
You load an XML file using the [mxmlLoadFile](@@) function:

```c
mxml_node_t *
mxmlLoadFile(mxml_node_t *top, FILE *fp,
mxml_load_cb_t load_cb, void *load_cbdata,
mxml_sax_cb_t sax_cb, void *sax_cbdata);
mxmlLoadFilename(mxml_node_t *top, const char *filename,
mxml_load_cb_t load_cb, void *load_cbdata,
mxml_sax_cb_t sax_cb, void *sax_cbdata);
```

The `load_cb` argument specifies a function that assigns child (value) node
Expand All @@ -110,18 +116,16 @@ nodes. For example, to load the XML file "filename.xml" containing literal
strings you can use:

```c
FILE *fp;
mxml_node_t *tree;
mxml_type_t type = MXML_TYPE_OPAQUE;
fp = fopen("filename.xml", "r");
tree = mxmlLoadFile(/*top*/NULL, fp, /*load_cb*/NULL, &type,
/*sax_cb*/NULL, /*sax_cbdata*/NULL);
fclose(fp);
tree = mxmlLoadFilename(/*top*/NULL, "filename.xml",
/*load_cb*/NULL, /*load_cbdata*/&type,
/*sax_cb*/NULL, /*sax_cbdata*/NULL);
```

Mini-XML also provides functions to load from a named file, a file descriptor,
or string:
Mini-XML also provides functions to load from a `FILE` pointer, a file
descriptor, or string:

```c
mxml_node_t *
Expand All @@ -130,9 +134,9 @@ mxmlLoadFd(mxml_node_t *top, int fd,
mxml_sax_cb_t sax_cb, void *sax_cbdata);
mxml_node_t *
mxmlLoadFilename(mxml_node_t *top, const char *filename,
mxml_load_cb_t load_cb, void *load_cbdata,
mxml_sax_cb_t sax_cb, void *sax_cbdata);
mxmlLoadFile(mxml_node_t *top, FILE *fp,
mxml_load_cb_t load_cb, void *load_cbdata,
mxml_sax_cb_t sax_cb, void *sax_cbdata);
mxml_node_t *
mxmlLoadString(mxml_node_t *top, const char *s,
Expand All @@ -143,26 +147,27 @@ mxmlLoadString(mxml_node_t *top, const char *s,

### Load Callbacks

The `load_xxx` arguments to the `mxmlLoad` functions are a callback function and
a data pointer which are used to determine the value type of each data node in
an XML document. The default (`NULL`) callback expects the `load_cbdata`
argument to be a pointer to a `mxml_type_t` variable - if `NULL` it returns the
`MXML_TYPE_TEXT` type.
The `load_xxx` arguments to the mxmlLoadXxx functions are a callback function
and a data pointer which are used to determine the value type of each data node
in an XML document. The default (`NULL`) callback expects the `load_cbdata`
argument to be a pointer to a `mxml_type_t` variable that contains the desired
value node type - if `NULL`, it uses the `MXML_TYPE_TEXT` (whitespace-separated
text) type.

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:
You can provide your own callback function 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:
`MXML_TYPE_CUSTOM`, `MXML_TYPE_INTEGER`, `MXML_TYPE_OPAQUE`, `MXML_TYPE_REAL`,
or `MXML_TYPE_TEXT`. The function is called *after* the element and its
attributes have been read, so you can look at the element name, attributes, and
attributes have been read so you can look at the element name, attributes, and
attribute values to determine the proper value type to return.

The following callback function looks for an attribute named "type" or the
element name to determine the value type for its child nodes:

```c
mxml_type_t
type_cb(void *cbdata, mxml_node_t *node)
my_load_cb(void *cbdata, mxml_node_t *node)
{
const char *type;
Expand All @@ -174,6 +179,8 @@ type_cb(void *cbdata, mxml_node_t *node)
type = mxmlElementGetAttr(node, "type");
if (type == NULL)
type = mxmlGetElement(node);
if (type == NULL)
type = "text";
if (!strcmp(type, "integer"))
return (MXML_TYPE_INTEGER);
Expand All @@ -186,18 +193,15 @@ type_cb(void *cbdata, mxml_node_t *node)
}
```

To use this callback function, simply use the name when you call any of the load
To use this callback function, simply specify it when you call any of the load
functions:

```c
FILE *fp;
mxml_node_t *tree;
fp = fopen("filename.xml", "r");
tree = mxmlLoadFile(/*top*/NULL, fp,
type_cb, /*load_cbdata*/NULL,
/*sax_cb*/NULL, /*sax_cbata*/NULL);
fclose(fp);
tree = mxmlLoadFilename(/*top*/NULL, "filename.xml",
my_load_cb, /*load_cbdata*/NULL,
/*sax_cb*/NULL, /*sax_cbdata*/NULL);
```


Expand Down Expand Up @@ -242,7 +246,7 @@ the node tree for the file would look like the following in memory:
where "-" is a pointer to the sibling node and "|" is a pointer to the first
child or parent node.

The `mxmlGetType` function gets the type of a node:
The [mxmlGetType](@@) function gets the type of a node:

```c
mxml_type_t
Expand All @@ -261,10 +265,10 @@ mxmlGetType(mxml_node_t *node);
- `MXML_TYPE_REAL` : A whitespace-delimited floating point value, or
- `MXML_TYPE_TEXT` : A whitespace-delimited text (fragment) value.

The parent and sibling nodes are accessed using the `mxmlGetParent`,
`mxmlGetNextSibling`, and `mxmlGetPreviousSibling` functions, while the children
of an element node are accessed using the `mxmlGetFirstChild` or
`mxmlGetLastChild` functions:
The parent and sibling nodes are accessed using the [mxmlGetParent](@@),
[mxmlGetNextSibling](@@), and [mxmlGetPreviousSibling](@@) functions, while the
children of an element node are accessed using the [mxmlGetFirstChild](@@) or
[mxmlGetLastChild](@@) functions:

```c
mxml_node_t *
Expand All @@ -283,8 +287,8 @@ mxml_node_t *
mxmlGetPrevSibling(mxml_node_t *node);
```

The `mxmlGetUserData` function gets any user (application) data associated with
the node:
The [mxmlGetUserData](@@) function gets any user (application) data associated
with the node:

```c
void *
Expand Down
39 changes: 13 additions & 26 deletions doc/mxml.3
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.TH mxml 3 "Mini-XML API" "2024-03-06" "Mini-XML API"
.TH mxml 3 "Mini-XML API" "2024-03-07" "Mini-XML API"
.SH NAME
mxml \- Mini-XML API
.SH INCLUDE FILE
Expand Down Expand Up @@ -1315,22 +1315,6 @@ bool mxmlSetCustom (
.fi
.PP
The node is not changed if it (or its first child) is not a custom node.
.SS mxmlSetCustomCallbacks
Set the handling functions for custom data.
.PP
.nf
void mxmlSetCustomCallbacks (
mxml_custom_load_cb_t load_cb,
mxml_custom_save_cb_t save_cb,
void *cbdata
);
.fi
.PP
The load function accepts a node pointer and a data string and must
return 0 on success and non-zero on error.
.PP
The save function accepts a node pointer and must return a malloc'd
string on success and \fBNULL\fR on error.
.SS mxmlSetDeclaration
Set a comment to a literal string.
.PP
Expand Down Expand Up @@ -1380,15 +1364,6 @@ bool mxmlSetElement (
.fi
.PP
The node is not changed if it is not an element node.
.SS mxmlSetErrorCallback
Set the error message callback.
.PP
.nf
void mxmlSetErrorCallback (
mxml_error_cb_t cb,
void *cbdata
);
.fi
.SS mxmlSetInteger
Set the value of an integer node.
.PP
Expand Down Expand Up @@ -1591,6 +1566,18 @@ SAX event type.
.nf
typedef enum mxml_sax_event_e mxml_sax_event_t;
.fi
.SS mxml_strcopy_cb_t
String copy/allocation callback
.PP
.nf
typedef char *(*)(void *cbdata const char *s) mxml_strcopy_cb_t;
.fi
.SS mxml_strfree_cb_t
String free callback
.PP
.nf
typedef void(*)(void *cbdata char *s) mxml_strfree_cb_t;
.fi
.SS mxml_type_t
The XML node type.
.PP
Expand Down
Binary file modified doc/mxml.epub
Binary file not shown.
44 changes: 12 additions & 32 deletions doc/mxml.html
Original file line number Diff line number Diff line change
Expand Up @@ -356,13 +356,11 @@ <h2 class="title">Contents</h2>
<li><a href="#mxmlSetComment">mxmlSetComment</a></li>
<li><a href="#mxmlSetCommentf">mxmlSetCommentf</a></li>
<li><a href="#mxmlSetCustom">mxmlSetCustom</a></li>
<li><a href="#mxmlSetCustomCallbacks">mxmlSetCustomCallbacks</a></li>
<li><a href="#mxmlSetDeclaration">mxmlSetDeclaration</a></li>
<li><a href="#mxmlSetDeclarationf">mxmlSetDeclarationf</a></li>
<li><a href="#mxmlSetDirective">mxmlSetDirective</a></li>
<li><a href="#mxmlSetDirectivef">mxmlSetDirectivef</a></li>
<li><a href="#mxmlSetElement">mxmlSetElement</a></li>
<li><a href="#mxmlSetErrorCallback">mxmlSetErrorCallback</a></li>
<li><a href="#mxmlSetInteger">mxmlSetInteger</a></li>
<li><a href="#mxmlSetOpaque">mxmlSetOpaque</a></li>
<li><a href="#mxmlSetOpaquef">mxmlSetOpaquef</a></li>
Expand All @@ -389,6 +387,8 @@ <h2 class="title">Contents</h2>
<li><a href="#mxml_save_cb_t">mxml_save_cb_t</a></li>
<li><a href="#mxml_sax_cb_t">mxml_sax_cb_t</a></li>
<li><a href="#mxml_sax_event_t">mxml_sax_event_t</a></li>
<li><a href="#mxml_strcopy_cb_t">mxml_strcopy_cb_t</a></li>
<li><a href="#mxml_strfree_cb_t">mxml_strfree_cb_t</a></li>
<li><a href="#mxml_type_t">mxml_type_t</a></li>
<li><a href="#mxml_write_cb_t">mxml_write_cb_t</a></li>
<li><a href="#mxml_ws_t">mxml_ws_t</a></li>
Expand Down Expand Up @@ -2600,25 +2600,6 @@ <h4 class="returnvalue">Return Value</h4>
<p class="description"><code>true</code> on success, <code>false</code> on failure</p>
<h4 class="discussion">Discussion</h4>
<p class="discussion">The node is not changed if it (or its first child) is not a custom node.</p>
<h3 class="function"><a id="mxmlSetCustomCallbacks">mxmlSetCustomCallbacks</a></h3>
<p class="description">Set the handling functions for custom data.</p>
<p class="code">
void mxmlSetCustomCallbacks(<a href="#mxml_custom_load_cb_t">mxml_custom_load_cb_t</a> load_cb, <a href="#mxml_custom_save_cb_t">mxml_custom_save_cb_t</a> save_cb, void *cbdata);</p>
<h4 class="parameters">Parameters</h4>
<table class="list"><tbody>
<tr><th>load_cb</th>
<td class="description">Load callback function</td></tr>
<tr><th>save_cb</th>
<td class="description">Save callback function</td></tr>
<tr><th>cbdata</th>
<td class="description">Callback data</td></tr>
</tbody></table>
<h4 class="discussion">Discussion</h4>
<p class="discussion">The load function accepts a node pointer and a data string and must
return 0 on success and non-zero on error.<br>
<br>
The save function accepts a node pointer and must return a malloc'd
string on success and <code>NULL</code> on error.</p>
<h3 class="function"><a id="mxmlSetDeclaration">mxmlSetDeclaration</a></h3>
<p class="description">Set a comment to a literal string.</p>
<p class="code">
Expand Down Expand Up @@ -2690,17 +2671,6 @@ <h4 class="returnvalue">Return Value</h4>
<p class="description"><code>true</code> on success, <code>false</code> on failure</p>
<h4 class="discussion">Discussion</h4>
<p class="discussion">The node is not changed if it is not an element node.</p>
<h3 class="function"><a id="mxmlSetErrorCallback">mxmlSetErrorCallback</a></h3>
<p class="description">Set the error message callback.</p>
<p class="code">
void mxmlSetErrorCallback(<a href="#mxml_error_cb_t">mxml_error_cb_t</a> cb, void *cbdata);</p>
<h4 class="parameters">Parameters</h4>
<table class="list"><tbody>
<tr><th>cb</th>
<td class="description">Error callback function</td></tr>
<tr><th>cbdata</th>
<td class="description">Error callback data</td></tr>
</tbody></table>
<h3 class="function"><a id="mxmlSetInteger">mxmlSetInteger</a></h3>
<p class="description">Set the value of an integer node.</p>
<p class="code">
Expand Down Expand Up @@ -2932,6 +2902,16 @@ <h3 class="typedef"><a id="mxml_sax_event_t">mxml_sax_event_t</a></h3>
<p class="code">
typedef enum <a href="#mxml_sax_event_e">mxml_sax_event_e</a> mxml_sax_event_t;
</p>
<h3 class="typedef"><a id="mxml_strcopy_cb_t">mxml_strcopy_cb_t</a></h3>
<p class="description">String copy/allocation callback</p>
<p class="code">
typedef char *(*mxml_strcopy_cb_t)(void *cbdata const char *s);
</p>
<h3 class="typedef"><a id="mxml_strfree_cb_t">mxml_strfree_cb_t</a></h3>
<p class="description">String free callback</p>
<p class="code">
typedef void (*mxml_strfree_cb_t)(void *cbdata char *s);
</p>
<h3 class="typedef"><a id="mxml_type_t">mxml_type_t</a></h3>
<p class="description">The XML node type.</p>
<p class="code">
Expand Down

0 comments on commit a9aea16

Please sign in to comment.