Skip to content

Commit

Permalink
SAX callback now returns a boolean (Issue #51)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelrsweet committed Mar 4, 2024
1 parent 5c66db0 commit 3df751f
Show file tree
Hide file tree
Showing 8 changed files with 62 additions and 32 deletions.
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
`MXML_TYPE_DIRECTIVE` node types (Issue #250)
- Renamed `mxml_type_t` enumerations to `MXML_TYPE_xxx` (Issue #251)
- Updated APIs to use bool type instead of an int representing a boolean value.
- Updated the SAX callback to return a `bool` value to control processing
(Issue #51)


# Changes in Mini-XML 3.3.2
Expand Down
4 changes: 2 additions & 2 deletions doc/body.man
Original file line number Diff line number Diff line change
Expand Up @@ -154,13 +154,13 @@ functions retrieve the value from a node:

mxml_node_t *node;

int intvalue = mxmlGetInteger(node);
long intvalue = mxmlGetInteger(node);

const char *opaquevalue = mxmlGetOpaque(node);

double realvalue = mxmlGetReal(node);

int whitespacevalue;
bool whitespacevalue;
const char *textvalue = mxmlGetText(node, &whitespacevalue);
.fi
.PP
Expand Down
24 changes: 16 additions & 8 deletions doc/body.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ The Mini-XML library is included with your program using the `-lmxml` option:
If you have the `pkg-config` software installed, you can use it to determine the
proper compiler and linker options for your installation:

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


Loading an XML File
Expand Down Expand Up @@ -1172,23 +1172,26 @@ mxmlSAXLoadString(mxml_node_t *top, const char *s,

Each function works like the corresponding `mxmlLoad` function but uses a
callback to process each node as it is read. The callback function receives the
node, an event code, and a user data pointer you supply:
node, an event code, and a user data pointer you supply and returns `true` to
continue processing or `false` to stop:

```c
void
bool
sax_cb(mxml_node_t *node, mxml_sax_event_t event,
void *data)
{
... do something ...
// Continue processing...
return (true);
}
```

The event will be one of the following:

- `MXML_SAX_EVENT_CDATA`: CDATA was just read.
- `MXML_SAX_EVENT_COMMENT`: A comment was just read.
- `MXML_SAX_EVENT_DATA`: Data (
--------------------, integer, opaque, real, or text) was just read.
- `MXML_SAX_EVENT_DATA`: Data (integer, opaque, real, or text) was just read.
- `MXML_SAX_EVENT_DECLARATION`: A declaration was just read.
- `MXML_SAX_EVENT_DIRECTIVE`: A processing directive/instruction was just read.
- `MXML_SAX_EVENT_ELEMENT_CLOSE` - A close element was just read \(`</element>`)
Expand All @@ -1200,12 +1203,14 @@ using the `mxmlRetain` function. For example, the following SAX callback will
retain all nodes, effectively simulating a normal in-memory load:

```c
void
bool
sax_cb(mxml_node_t *node, mxml_sax_event_t event,
void *data)
{
if (event != MXML_SAX_ELEMENT_CLOSE)
mxmlRetain(node);
return (true);
}
```

Expand All @@ -1216,7 +1221,7 @@ will retain the title and headings in an XHTML file. It also retains the
directives like `<?xml ... ?>` and declarations like `<!DOCTYPE ... >`:

```c
void
bool
sax_cb(mxml_node_t *node, mxml_sax_event_t event,
void *data)
{
Expand Down Expand Up @@ -1256,6 +1261,8 @@ sax_cb(mxml_node_t *node, mxml_sax_event_t event,
mxmlRetain(node);
}
}
return (true);
}
```

Expand Down Expand Up @@ -1320,7 +1327,8 @@ Migrating from Mini-XML v3.x

The following incompatible API changes were made in Mini-XML v4.0:

- SAX events are not named `MXML_SAX_EVENT_foo` instead of `MXML_SAX_foo`.
- SAX events are now named `MXML_SAX_EVENT_foo` instead of `MXML_SAX_foo`.
- SAX callbacks now return a boolean value.
- Node types are now named `MXML_TYPE_foo` instead of `MXML_foo`.
- Functions that returned `0` on success and `-1` on error now return `true` on
success and `false` on error.
Expand Down
8 changes: 4 additions & 4 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-02" "Mini-XML API"
.TH mxml 3 "Mini-XML API" "2024-03-04" "Mini-XML API"
.SH NAME
mxml \- Mini-XML API
.SH INCLUDE FILE
Expand Down Expand Up @@ -157,13 +157,13 @@ functions retrieve the value from a node:

mxml_node_t *node;

int intvalue = mxmlGetInteger(node);
long intvalue = mxmlGetInteger(node);

const char *opaquevalue = mxmlGetOpaque(node);

double realvalue = mxmlGetReal(node);

int whitespacevalue;
bool whitespacevalue;
const char *textvalue = mxmlGetText(node, &whitespacevalue);
.fi
.PP
Expand Down Expand Up @@ -1505,7 +1505,7 @@ typedef const char *(*)(mxml_node_t *, int) mxml_save_cb_t;
SAX callback function
.PP
.nf
typedef void(*)(mxml_node_t *, mxml_sax_event_t, void *) mxml_sax_cb_t;
typedef bool(*)(mxml_node_t *, mxml_sax_event_t, void *) mxml_sax_cb_t;
.fi
.SS mxml_sax_event_t
SAX event type.
Expand Down
Binary file modified doc/mxml.epub
Binary file not shown.
25 changes: 17 additions & 8 deletions doc/mxml.html
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ <h2 class="title" id="using-mini-xml">Using Mini-XML</h2>
<pre><code>gcc -o myprogram myprogram.c -lmxml
</code></pre>
<p>If you have the <code>pkg-config</code> software installed, you can use it to determine the proper compiler and linker options for your installation:</p>
<pre><code>gcc `pkg-config --cflags mxml` -o myprogram myprogram.c `pkg-config --libs mxml`
<pre><code>gcc `pkg-config --cflags mxml4` -o myprogram myprogram.c `pkg-config --libs mxml4`
</code></pre>
<h3 class="title" id="loading-an-xml-file">Loading an XML File</h3>
<p>You load an XML file using the <code>mxmlLoadFile</code> function:</p>
Expand Down Expand Up @@ -1151,12 +1151,15 @@ <h2 class="title" id="sax-stream-loading-of-documents">SAX (Stream) Loading of D
mxml_type_t (*cb)(mxml_node_t *),
mxml_sax_cb_t sax, <span class="reserved">void</span> *sax_data);
</code></pre>
<p>Each function works like the corresponding <code>mxmlLoad</code> function but uses a callback to process each node as it is read. The callback function receives the node, an event code, and a user data pointer you supply:</p>
<pre><code class="language-c"><span class="reserved">void</span>
<p>Each function works like the corresponding <code>mxmlLoad</code> function but uses a callback to process each node as it is read. The callback function receives the node, an event code, and a user data pointer you supply and returns <code>true</code> to continue processing or <code>false</code> to stop:</p>
<pre><code class="language-c"><span class="reserved">bool</span>
sax_cb(mxml_node_t *node, mxml_sax_event_t event,
<span class="reserved">void</span> *data)
{
... <span class="reserved">do</span> something ...

<span class="comment">// Continue processing...</span>
<span class="reserved">return</span> (<span class="reserved">true</span>);
}
</code></pre>
<p>The event will be one of the following:</p>
Expand All @@ -1165,7 +1168,7 @@ <h2 class="title" id="sax-stream-loading-of-documents">SAX (Stream) Loading of D
</li>
<li><p><code>MXML_SAX_EVENT_COMMENT</code>: A comment was just read.</p>
</li>
<li><p><code>MXML_SAX_EVENT_DATA</code>: Data ( --------------------, integer, opaque, real, or text) was just read.</p>
<li><p><code>MXML_SAX_EVENT_DATA</code>: Data (integer, opaque, real, or text) was just read.</p>
</li>
<li><p><code>MXML_SAX_EVENT_DECLARATION</code>: A declaration was just read.</p>
</li>
Expand All @@ -1177,16 +1180,18 @@ <h2 class="title" id="sax-stream-loading-of-documents">SAX (Stream) Loading of D
</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 <code>mxmlRetain</code> function. For example, the following SAX callback will retain all nodes, effectively simulating a normal in-memory load:</p>
<pre><code class="language-c"><span class="reserved">void</span>
<pre><code class="language-c"><span class="reserved">bool</span>
sax_cb(mxml_node_t *node, mxml_sax_event_t event,
<span class="reserved">void</span> *data)
{
<span class="reserved">if</span> (event != MXML_SAX_ELEMENT_CLOSE)
mxmlRetain(node);

<span class="reserved">return</span> (<span class="reserved">true</span>);
}
</code></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 <code>&lt;html&gt;</code>, <code>&lt;head&gt;</code>, and <code>&lt;body&gt;</code>, and processing directives like <code>&lt;?xml ... ?&gt;</code> and declarations like <code>&lt;!DOCTYPE ... &gt;</code>:</p>
<pre><code class="language-c"><span class="reserved">void</span>
<pre><code class="language-c"><span class="reserved">bool</span>
sax_cb(mxml_node_t *node, mxml_sax_event_t event,
<span class="reserved">void</span> *data)
{
Expand Down Expand Up @@ -1226,6 +1231,8 @@ <h2 class="title" id="sax-stream-loading-of-documents">SAX (Stream) Loading of D
mxmlRetain(node);
}
}

<span class="reserved">return</span> (<span class="reserved">true</span>);
}
</code></pre>
<p>The resulting skeleton document tree can then be searched just like one loaded using the <code>mxmlLoad</code> 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>
Expand Down Expand Up @@ -1277,7 +1284,9 @@ <h2 class="title" id="sax-stream-loading-of-documents">SAX (Stream) Loading of D
<h2 class="title" id="migrating-from-mini-xml-v3.x">Migrating from Mini-XML v3.x</h2>
<p>The following incompatible API changes were made in Mini-XML v4.0:</p>
<ul>
<li><p>SAX events are not named <code>MXML_SAX_EVENT_foo</code> instead of <code>MXML_SAX_foo</code>.</p>
<li><p>SAX events are now named <code>MXML_SAX_EVENT_foo</code> instead of <code>MXML_SAX_foo</code>.</p>
</li>
<li><p>SAX callbacks now return a boolean value.</p>
</li>
<li><p>Node types are now named <code>MXML_TYPE_foo</code> instead of <code>MXML_foo</code>.</p>
</li>
Expand Down Expand Up @@ -2874,7 +2883,7 @@ <h3 class="typedef"><a id="mxml_save_cb_t">mxml_save_cb_t</a></h3>
<h3 class="typedef"><a id="mxml_sax_cb_t">mxml_sax_cb_t</a></h3>
<p class="description">SAX callback function</p>
<p class="code">
typedef void (*mxml_sax_cb_t)(<a href="#mxml_node_t">mxml_node_t</a> *, mxml_sax_event_t, void *);
typedef bool (*mxml_sax_cb_t)(<a href="#mxml_node_t">mxml_node_t</a> *, mxml_sax_event_t, void *);
</p>
<h3 class="typedef"><a id="mxml_sax_event_t">mxml_sax_event_t</a></h3>
<p class="description">SAX event type.</p>
Expand Down
29 changes: 20 additions & 9 deletions mxml-file.c
Original file line number Diff line number Diff line change
Expand Up @@ -1341,7 +1341,8 @@ mxml_load_data(

if (sax_cb)
{
(*sax_cb)(node, MXML_SAX_EVENT_DATA, sax_data);
if (!(*sax_cb)(node, MXML_SAX_EVENT_DATA, sax_data))
goto error;

if (!mxmlRelease(node))
node = NULL;
Expand All @@ -1367,7 +1368,8 @@ mxml_load_data(

if (sax_cb)
{
(*sax_cb)(node, MXML_SAX_EVENT_DATA, sax_data);
if (!(*sax_cb)(node, MXML_SAX_EVENT_DATA, sax_data))
goto error;

if (!mxmlRelease(node))
node = NULL;
Expand Down Expand Up @@ -1464,7 +1466,8 @@ mxml_load_data(

if (sax_cb)
{
(*sax_cb)(node, MXML_SAX_EVENT_COMMENT, sax_data);
if (!(*sax_cb)(node, MXML_SAX_EVENT_COMMENT, sax_data))
goto error;

if (!mxmlRelease(node))
node = NULL;
Expand Down Expand Up @@ -1520,7 +1523,8 @@ mxml_load_data(

if (sax_cb)
{
(*sax_cb)(node, MXML_SAX_EVENT_CDATA, sax_data);
if (!(*sax_cb)(node, MXML_SAX_EVENT_CDATA, sax_data))
goto error;

if (!mxmlRelease(node))
node = NULL;
Expand Down Expand Up @@ -1570,7 +1574,8 @@ mxml_load_data(

if (sax_cb)
{
(*sax_cb)(node, MXML_SAX_EVENT_DIRECTIVE, sax_data);
if (!(*sax_cb)(node, MXML_SAX_EVENT_DIRECTIVE, sax_data))
goto error;

if (strncmp(node->value.directive, "xml ", 4) && !mxmlRelease(node))
node = NULL;
Expand Down Expand Up @@ -1645,7 +1650,8 @@ mxml_load_data(

if (sax_cb)
{
(*sax_cb)(node, MXML_SAX_EVENT_DECLARATION, sax_data);
if (!(*sax_cb)(node, MXML_SAX_EVENT_DECLARATION, sax_data))
goto error;

if (!mxmlRelease(node))
node = NULL;
Expand Down Expand Up @@ -1686,7 +1692,8 @@ mxml_load_data(

if (sax_cb)
{
(*sax_cb)(node, MXML_SAX_EVENT_ELEMENT_CLOSE, sax_data);
if (!(*sax_cb)(node, MXML_SAX_EVENT_ELEMENT_CLOSE, sax_data))
goto error;

if (!mxmlRelease(node))
{
Expand Down Expand Up @@ -1737,7 +1744,10 @@ mxml_load_data(
}

if (sax_cb)
(*sax_cb)(node, MXML_SAX_EVENT_ELEMENT_OPEN, sax_data);
{
if (!(*sax_cb)(node, MXML_SAX_EVENT_ELEMENT_OPEN, sax_data))
goto error;
}

if (!first)
first = node;
Expand All @@ -1757,7 +1767,8 @@ mxml_load_data(
}
else if (sax_cb)
{
(*sax_cb)(node, MXML_SAX_EVENT_ELEMENT_CLOSE, sax_data);
if (!(*sax_cb)(node, MXML_SAX_EVENT_ELEMENT_CLOSE, sax_data))
goto error;

if (!mxmlRelease(node))
{
Expand Down
2 changes: 1 addition & 1 deletion mxml.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ typedef mxml_type_t (*mxml_load_cb_t)(mxml_node_t *);
typedef const char *(*mxml_save_cb_t)(mxml_node_t *, int);
// Save callback function

typedef void (*mxml_sax_cb_t)(mxml_node_t *, mxml_sax_event_t, void *);
typedef bool (*mxml_sax_cb_t)(mxml_node_t *, mxml_sax_event_t, void *);
// SAX callback function


Expand Down

0 comments on commit 3df751f

Please sign in to comment.