diff --git a/CHANGES.md b/CHANGES.md index c2f4714..d36b2c2 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -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 diff --git a/doc/body.man b/doc/body.man index 55bf45a..f9a6179 100644 --- a/doc/body.man +++ b/doc/body.man @@ -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 diff --git a/doc/body.md b/doc/body.md index 87495e0..aa30a83 100644 --- a/doc/body.md +++ b/doc/body.md @@ -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 @@ -1172,14 +1172,18 @@ 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); } ``` @@ -1187,8 +1191,7 @@ 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 \(``) @@ -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); } ``` @@ -1216,7 +1221,7 @@ will retain the title and headings in an XHTML file. It also retains the directives like `` and declarations like ``: ```c -void +bool sax_cb(mxml_node_t *node, mxml_sax_event_t event, void *data) { @@ -1256,6 +1261,8 @@ sax_cb(mxml_node_t *node, mxml_sax_event_t event, mxmlRetain(node); } } + + return (true); } ``` @@ -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. diff --git a/doc/mxml.3 b/doc/mxml.3 index 963a10a..1f82030 100644 --- a/doc/mxml.3 +++ b/doc/mxml.3 @@ -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 @@ -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 @@ -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. diff --git a/doc/mxml.epub b/doc/mxml.epub index dd23593..761980e 100644 Binary files a/doc/mxml.epub and b/doc/mxml.epub differ diff --git a/doc/mxml.html b/doc/mxml.html index 3414cf1..eed8ec7 100644 --- a/doc/mxml.html +++ b/doc/mxml.html @@ -437,7 +437,7 @@ span.string {
gcc -o myprogram myprogram.c -lmxml
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
You load an XML file using the mxmlLoadFile
function:
@@ -1151,12 +1151,15 @@ mxmlSAXLoadString(mxml_node_t *top, const void *sax_data);
-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:
void
+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 and returns true
to continue processing or false
to stop:
+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:
@@ -1165,7 +1168,7 @@ sax_cb(mxml_node_t *node, mxml_sax_event_t event,
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.
@@ -1177,16 +1180,18 @@ sax_cb(mxml_node_t *node, mxml_sax_event_t event,
Elements are released after the close element is processed. All other nodes are released after they are processed. The SAX callback can retain the node using the mxmlRetain
function. For example, the following SAX callback will retain all nodes, effectively simulating a normal in-memory load:
-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);
}
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 <html>
, <head>
, and <body>
, and processing directives like <?xml ... ?>
and declarations like <!DOCTYPE ... >
:
-void
+bool
sax_cb(mxml_node_t *node, mxml_sax_event_t event,
void *data)
{
@@ -1226,6 +1231,8 @@ sax_cb(mxml_node_t *node, mxml_sax_event_t event,
mxmlRetain(node);
}
}
+
+ return (true);
}
The resulting skeleton document tree can then be searched just like one loaded using the mxmlLoad
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:
@@ -1277,7 +1284,9 @@ print_children(mxml_node_t *parent)
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
.
@@ -2874,7 +2883,7 @@ typedef const char *(*mxml_save_cb_t)(mxml_node_t *,
mxml_sax_cb_t
SAX 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 *);
mxml_sax_event_t
SAX event type.
diff --git a/mxml-file.c b/mxml-file.c
index 5f7f78b..8a93ab6 100644
--- a/mxml-file.c
+++ b/mxml-file.c
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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))
{
@@ -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;
@@ -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))
{
diff --git a/mxml.h b/mxml.h
index 71427e4..71634b1 100644
--- a/mxml.h
+++ b/mxml.h
@@ -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