diff --git a/CHANGES.md b/CHANGES.md index 5cef3ef..d4680ef 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -11,6 +11,8 @@ - The mxmldoc utility now supports the `SOURCE_DATE_EPOCH` environment variable for reproducible builds (Issue #193) - The mxmldoc utility now supports Markdown (Issue #194) +- Added `mxmlNewOpaquef` and `mxmlSetOpaquef` functions to add and set formatted + opaque string values. # Changes in Mini-XML 2.10 diff --git a/Makefile.in b/Makefile.in index 487a5c7..eef14fe 100644 --- a/Makefile.in +++ b/Makefile.in @@ -360,7 +360,10 @@ testmxml.o: mxml.h # mxml.xml # -mxml.xml: mxmldoc-static mxml.h $(PUBLIBOBJS:.o=.c) +mxml.xml: mxmldoc-static mxml.h $(PUBLIBOBJS:.o=.c) \ + doc/body.man doc/body.md \ + doc/docset.css doc/docset.header \ + doc/reference.header echo Generating API documentation... $(RM) mxml.xml ./mxmldoc-static --header doc/reference.header \ @@ -390,13 +393,9 @@ mxml.xml: mxmldoc-static mxml.h $(PUBLIBOBJS:.o=.c) # mxml.epub # -mxml.epub: mxml.xml +mxml.epub: mxml.xml doc/body.md doc/mxml-cover.png echo Generating EPUB API documentation... - ./mxmldoc-static --header doc/docset.header \ - --body doc/body.md \ - --docversion @VERSION@ --author "Michael R Sweet" \ - --copyright "Copyright 2003-2017, All Rights Reserved." \ - --title "Mini-XML API Reference" \ + ./mxmldoc-static --body doc/body.md \ --coverimage doc/mxml-cover.png \ --epub mxml.epub mxml.xml diff --git a/doc/body.md b/doc/body.md index 6afa7f6..0385663 100644 --- a/doc/body.md +++ b/doc/body.md @@ -1,7 +1,7 @@ --- title: Mini-XML API Reference author: Michael R Sweet -copyright: Copyright (c) 2003-2017, All Rights Reserved. +copyright: Copyright © 2003-2017, All Rights Reserved. docversion: 2.11 ... @@ -27,61 +27,650 @@ Mini-XML provides the following functionality: Mini-XML doesn't do validation or other types of processing on the data based upon schema files or other sources of definition information. + +## History + +Mini-XML was initially developed for the [Gutenprint](http://gutenprint.sf.net/) +project to replace the rather large and unwieldy `libxml2` 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: + +> It's bad enough that we require libxml2, but rolling our own XML parser is a +> bit more than we can handle. + +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 +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 4,115 lines of code, compared to 140,410 lines of code for libxml2 +version 2.9.1. + + +## Resources + +The Mini-XML home page can be found at: + + https://michaelrsweet.github.io/mxml + +From here you can download the current version of Mini-XML, the issue tracker, +and other resources. + + +## Legal Stuff + +The Mini-XML library is copyright © 2003-2017 by Michael R Sweet and is provided +under version 2 of the GNU Library General Public License (LGPL2) with the +following exceptions: + +1. 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. + + 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. + +2. 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. + +A copy of the complete license is available in the file `COPYING` provided with +the source code. + + # Using Mini-XML Mini-XML provides a single header file which you include: #include -Nodes are defined by the `mxml_node_t` structure; the "type" member defines the -node type (element, integer, opaque, real, or text) which determines which value -you want to look at in the "value" union. New nodes can be created using the -`mxmlNewElement`, `mxmlNewInteger`, `mxmlNewOpaque`, `mxmlNewReal`, and -`mxmlNewText` functions. Only elements can have child nodes, and the top node -must be an element, usually "?xml". +The Mini-XML library is included with your program using the `-lmxml` option: + + 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` + + +## Loading an XML File You load an XML file using the `mxmlLoadFile` function: + mxml_node_t * + mxmlLoadFile(mxml_node_t *top, FILE *fp, + mxml_type_t (*cb)(mxml_node_t *)); + +The `cb` argument specifies a function that assigns child (value) node types for +each element in the document. The callback can be a function you provide or one +of the standard functions provided with Mini-XML. For example, to load the XML +file "filename.xml" containing text strings you can use the +`MXML_OPAQUE_CALLBACK` function: + FILE *fp; mxml_node_t *tree; fp = fopen("filename.xml", "r"); - tree = mxmlLoadFile(NULL, fp, MXML_NO_CALLBACK); + tree = mxmlLoadFile(NULL, fp, MXML_OPAQUE_CALLBACK); fclose(fp); -Similarly, you save an XML file using the `mxmlSaveFile` function: +Mini-XML also provides functions to load from a file descriptor or string: + + mxml_node_t * + mxmlLoadFd(mxml_node_t *top, int fd, + mxml_type_t (*cb)(mxml_node_t *)); + + mxml_node_t * + mxmlLoadString(mxml_node_t *top, const char *s, + mxml_type_t (*cb)(mxml_node_t *)); + + +### Load Callbacks + +The last argument to the `mxmlLoad` functions is a callback function which is +used to determine the value type of each data node in an XML document. Mini-XML +defines several standard callbacks for simple XML data files: + +- `MXML_INTEGER_CALLBACK`: All data nodes contain whitespace-separated integers. +- `MXML_OPAQUE_CALLBACK`: All data nodes contain opaque strings with whitespace preserved. +- `MXML_REAL_CALLBACK` - All data nodes contain whitespace-separated floating-point numbers. +- `MXML_TEXT_CALLBACK` - All data nodes contain whitespace-separated strings. + +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: +`MXML_CUSTOM`, `MXML_INTEGER`, `MXML_OPAQUE`, `MXML_REAL`, or `MXML_TEXT`. The +function is called *after* 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. + +The following callback function looks for an attribute named "type" or the +element name to determine the value type for its child nodes: + + 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); + } + +To use this callback function, simply use the name when you call any of the load +functions: FILE *fp; mxml_node_t *tree; + fp = fopen("filename.xml", "r"); + tree = mxmlLoadFile(NULL, fp, type_cb); + fclose(fp); + + +## Nodes + +Every piece of information in an XML file is stored in memory in "nodes". Nodes +are defined by the `mxml_node_t` structure. Each node has a typed value, +optional user data, a parent node, sibling nodes (previous and next), and +potentially child nodes. + +For example, if you have an XML file like the following: + + + + val1 + val2 + val3 + + val4 + val5 + val6 + + val7 + val8 + + +the node tree for the file would look like the following in memory: + + ?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 + +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: + + mxml_type_t + mxmlGetType(mxml_node_t *node); + +- `MXML_CUSTOM` : A custom value defined by your application, +- `MXML_ELEMENT` : An XML element, CDATA, comment, or processing instruction, +- `MXML_INTEGER` : A whitespace-delimited integer value, +- `MXML_OPAQUE` : An opaque string value that preserves all whitespace, +- `MXML_REAL` : A whitespace-delimited floating point value, or +- `MXML_TEXT` : A whitespace-delimited text (fragment) value. + +> Note: CDATA, comment, and processing directive nodes are currently stored in +> memory as special elements. This will be changed in a future major release of +> Mini-XML. + +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: + + mxml_node_t * + mxmlGetFirstChild(mxml_node_t *node); + + mxml_node_t * + mxmlGetLastChild(mxml_node_t *node); + + mxml_node_t * + mxmlGetNextSibling(mxml_node_t *node); + + mxml_node_t * + mxmlGetParent(mxml_node_t *node); + + mxml_node_t * + mxmlGetPrevSibling(mxml_node_t *node); + +The `mxmlGetUserData` function gets any user (application) data associated with +the node: + + void * + mxmlGetUserData(mxml_node_t *node); + + +## Creating XML Documents + +You can create and update XML documents in memory using the various `mxmlNew` +functions. The following code will create the XML document described in the +previous section: + + mxml_node_t *xml; /* */ + mxml_node_t *data; /* */ + mxml_node_t *node; /* */ + mxml_node_t *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"); + +We start by creating the declaration node common to all XML files using the +`mxmlNewXML` function: + + xml = mxmlNewXML("1.0"); + +We then create the `` node used for this document using the +`mxmlNewElement` function. The first argument specifies the parent node +\(`xml`) while the second specifies the element name \(`data`): + + data = mxmlNewElement(xml, "data"); + +Each `...` in the file is created using the `mxmlNewElement` and +`mxmlNewText` functions. The first argument of `mxmlNewText` specifies the +parent node \(`node`). 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: + + node = mxmlNewElement(data, "node"); + mxmlNewText(node, 0, "val1"); + +The resulting in-memory XML document can then be saved or processed just like +one loaded from disk or a string. + + +## Saving an XML File + +You save an XML file using the `mxmlSaveFile` function: + + int + mxmlSaveFile(mxml_node_t *node, FILE *fp, + mxml_save_cb_t cb); + +The `cb` argument specifies a function that returns the whitespace (if any) that +is inserted before and after each element node. The `MXML_NO_CALLBACK` constant +tells Mini-XML to not include any extra whitespace. For example, so save an XML +file to the file "filename.xml" with no extra whitespace: + + FILE *fp; + fp = fopen("filename.xml", "w"); - mxmlSaveFile(tree, fp, MXML_NO_CALLBACK); + mxmlSaveFile(xml, fp, MXML_NO_CALLBACK); fclose(fp); -The `mxmlLoadString`, `mxmlSaveAllocString`, and `mxmlSaveString` functions -load XML node trees from and save XML node trees to strings: +Mini-XML also provides functions to save to a file descriptor or strings: + + char * + mxmlSaveAllocString(mxml_node_t *node, mxml_save_cb_t cb); + + int + mxmlSaveFd(mxml_node_t *node, int fd, mxml_save_cb_t cb); + + int + mxmlSaveString(mxml_node_t *node, char *buffer, int bufsize, + mxml_save_cb_t cb); + + +### Controlling Line Wrapping + +When saving XML documents, Mini-XML normally wraps output lines at column 75 so +that the text is readable in terminal windows. The `mxmlSetWrapMargin` function +overrides the default wrap margin for the current thread: + + void mxmlSetWrapMargin(int column); + +For example, the following code sets the margin to 132 columns: + + mxmlSetWrapMargin(132); + +while the following code disables wrapping by setting the margin to 0: + + mxmlSetWrapMargin(0); + - char buffer[8192]; - char *ptr; +### Save Callbacks + +The last argument to the `mxmlSave` functions is a callback function which is +used to automatically insert whitespace in an XML document. 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 `MXML_WS_BEFORE_OPEN`, `MXML_WS_AFTER_OPEN`, +`MXML_WS_BEFORE_CLOSE`, or `MXML_WS_AFTER_CLOSE`. The callback function should +return `NULL` if no whitespace should be added or the string to insert (spaces, +tabs, carriage returns, and newlines) otherwise. + +The following whitespace callback can be used to add whitespace to XHTML output +to make it more readable in a standard text editor: + + const char * + whitespace_cb(mxml_node_t *node, int where) + { + const char *element; + + /* + * We can conditionally break to a new line before or after + * any element. These are just common HTML elements... + */ + + element = mxmlGetElement(node); + + if (!strcmp(element, "html") || + !strcmp(element, "head") || + !strcmp(element, "body") || + !strcmp(element, "pre") || + !strcmp(element, "p") || + !strcmp(element, "h1") || + !strcmp(element, "h2") || + !strcmp(element, "h3") || + !strcmp(element, "h4") || + !strcmp(element, "h5") || + !strcmp(element, "h6")) + { + /* + * Newlines before open and after close... + */ + + if (where == MXML_WS_BEFORE_OPEN || + where == MXML_WS_AFTER_CLOSE) + return ("\n"); + } + else if (!strcmp(element, "dl") || + !strcmp(element, "ol") || + !strcmp(element, "ul")) + { + /* + * Put a newline before and after list elements... + */ + + return ("\n"); + } + else if (!strcmp(element, "dd") || + !strcmp(element, "dt") || + !strcmp(element, "li")) + { + /* + * Put a tab before
  • 's,
    's, and
    's, and a + * newline after them... + */ + + if (where == MXML_WS_BEFORE_OPEN) + return ("\t"); + else if (where == MXML_WS_AFTER_CLOSE) + return ("\n"); + } + + /* + * Otherwise return NULL for no added whitespace... + */ + + return (NULL); + } + +To use this callback function, simply use the name when you call any of the save +functions: + + FILE *fp; mxml_node_t *tree; - ... - tree = mxmlLoadString(NULL, buffer, MXML_NO_CALLBACK); + fp = fopen("filename.xml", "w"); + mxmlSaveFile(tree, fp, whitespace_cb); + fclose(fp); + + +## Memory Management + +Once you are done with the XML data, use the `mxmlDelete` function to +recursively free the memory that is used for a particular node or the entire +tree: + + void + mxmlDelete(mxml_node_t *tree); + +You can also use reference counting to manage memory usage. The `mxmlRetain` +and `mxmlRelease` functions increment and decrement a node's use count, +respectively. When the use count goes to zero, `mxmlRelease` automatically +calls `mxmlDelete` to actually free the memory used by the node tree. New nodes +start with a use count of 1. + + +# More About Nodes + +## Element Nodes + +Element \(`MXML_ELEMENT`) nodes are created using the `mxmlNewElement` function. +Element attributes are set using the `mxmlElementSetAttr` and +`mxmlElementSetAttrf` functions and cleared using the `mxmlElementDeleteAttr` +function: + + mxml_node_t * + mxmlNewElement(mxml_node_t *parent, const char *name); + + void + mxmlElementDeleteAttr(mxml_node_t *node, const char *name); + + void + mxmlElementSetAttr(mxml_node_t *node, const char *name, + const char *value); + + void + mxmlElementSetAttrf(mxml_node_t *node, const char *name, + const char *format, ...); + +Child nodes are added using the various `mxmlNew` functions. The top (root) +node must be an element, usually created by the `mxmlNewXML` function: + + mxml_node_t * + mxmlNewXML(const char *version); + +The `mxmlGetElement` function retrieves the element name, the +`mxmlElementGetAttr` function retrieves the value string for a named attribute +associated with the element. The `mxmlElementGetAttrByIndex` and +`mxmlElementGetAttrCount` functions retrieve attributes by index: + + const char * + mxmlGetElement(mxml_node_t *node); + + const char * + mxmlElementGetAttr(mxml_node_t *node, const char *name); + + const char * + mxmlElementGetAttrByIndex(mxml_node_t *node, int idx, + const char **name); + + int + mxmlElementGetAttrCount(mxml_node_t *node); + + +## CDATA Nodes + +CDATA \(`MXML_ELEMENT`) nodes are created using the `mxmlNewCDATA` function: + + mxml_node_t *mxmlNewCDATA(mxml_node_t *parent, const char *string); + +The `mxmlGetCDATA` function retrieves the CDATA string pointer for a node: + + const char *mxmlGetCDATA(mxml_node_t *node); + + +## Comment Nodes + +Because comments are currently stored as element nodes, comment +\(`MXML_ELEMENT`) nodes are created using the `mxmlNewElement` function by +including the surrounding "!--" and "--" characters in the element name, for +example: + + mxml_node_t *node = mxmlNewElement("!-- This is a comment --"); + +Similarly, the `mxmlGetElement` function retrieves the comment string pointer +for a node, which includes the surrounding "!--" and "--" characters. + + const char *comment = mxmlGetElement(node); + /* returns "!-- This is a comment --" */ + + +## Processing Instruction Nodes + +Because processing instructions are currently stored as element nodes, +processing instruction \(`MXML_ELEMENT`) nodes are created using the +`mxmlNewElement` function including the surrounding "?" characters: + + mxml_node_t *node = mxmlNewElement("?xml-stylesheet type=\"text/css\" href=\"style.css\"?"); + +The `mxmlGetElement` function retrieves the processing instruction string for a +node, including the surrounding "?" characters: + + const char *instr = mxmlGetElement(node); + /* returned "?xml-stylesheet type=\"text/css\" href=\"style.css\"?" */ + + +## Integer Nodes - ... - mxmlSaveString(tree, buffer, sizeof(buffer), - MXML_NO_CALLBACK); +Integer \(`MXML_INTEGER`) nodes are created using the `mxmlNewInteger` function: - ... - ptr = mxmlSaveAllocString(tree, MXML_NO_CALLBACK); + mxml_node_t * + mxmlNewInteger(mxml_node_t *parent, int integer); -You can find a named element/node using the `mxmlFindElement` function: +The `mxmlGetInteger` function retrieves the integer value for a node: - mxml_node_t *node = mxmlFindElement(tree, tree, "name", - "attr", "value", - MXML_DESCEND); + int + mxmlGetInteger(mxml_node_t *node); -The "name", "attr", and "value" arguments can be passed as `NULL` to act as + +## Opaque String Nodes + +Opaque string \(`MXML_OPAQUE`) nodes are created using the `mxmlNewOpaque` +function: + + mxml_node_t * + mxmlNewOpaque(mxml_node_t *parent, const char *opaque); + +The `mxmlGetOpaque` function retrieves the opaque string pointer for a node: + + const char * + mxmlGetOpaque(mxml_node_t *node); + + +## Text Nodes + +Whitespace-delimited text string \(`MXML_TEXT`) nodes are created using the +`mxmlNewText` and `mxmlNewTextf` functions. Each text node consists of a text +string and (leading) whitespace flag value. + + mxml_node_t * + mxmlNewText(mxml_node_t *parent, int whitespace, + const char *string); + + mxml_node_t * + mxmlNewTextf(mxml_node_t *parent, int whitespace, + const char *format, ...); + +The `mxmlGetText` function retrieves the text string pointer and whitespace +flag value for a node: + + const char * + mxmlGetText(mxml_node_t *node, int *whitespace); + + +## Real Number Nodes + +Real number \(`MXML_REAL`) nodes are created using the `mxmlNewReal` function: + + mxml_node_t * + mxmlNewReal(mxml_node_t *parent, double real); + +The `mxmlGetReal` function retrieves the real number for a node: + + double + mxmlGetReal(mxml_node_t *node); + + +# Locating Data in an XML Document + +Mini-XML provides many functions for enumerating, searching, and indexing XML +documents. + + +## Finding Nodes + +The `mxmlFindPath` function finds the (first) value node under a specific +element using a "path": + + mxml_node_t * + mxmlFindPath(mxml_node_t *node, const char *path); + +The `path` string can contain the "*" wildcard to match a single element node in +the hierarchy. For example, the following code will find the first "node" +element under the "group" element, first using an explicit path and then using a +wildcard: + + mxml_node_t *value = mxmlFindPath(xml, "data/group/node"); + + mxml_node_t *value = mxmlFindPath(xml, "data/*/node"); + +The `mxmlFindElement` function can be used to find a named element, optionally +matching an attribute and value: + + mxml_node_t * + mxmlFindElement(mxml_node_t *node, mxml_node_t *top, + const char *element, const char *attr, + const char *value, int descend); + +The "element", "attr", and "value" arguments can be passed as `NULL` to act as wildcards, e.g.: /* Find the first "a" element */ @@ -94,7 +683,7 @@ wildcards, e.g.: /* Find the first "a" element with "href" to a URL */ node = mxmlFindElement(tree, tree, "a", "href", - "http://www.easysw.com/~mike/mxml/", + "http://michaelrsweet.github.io/", MXML_DESCEND); /* Find the first element with a "src" attribute*/ @@ -102,43 +691,463 @@ wildcards, e.g.: MXML_DESCEND); /* Find the first element with a "src" = "foo.jpg" */ - node = mxmlFindElement(tree, tree, NULL, "src", - "foo.jpg", MXML_DESCEND); + node = mxmlFindElement(tree, tree, NULL, "src", "foo.jpg", + MXML_DESCEND); You can also iterate with the same function: mxml_node_t *node; - for (node = mxmlFindElement(tree, tree, "name", NULL, + for (node = mxmlFindElement(tree, tree, "element", NULL, NULL, MXML_DESCEND); node != NULL; - node = mxmlFindElement(node, tree, "name", NULL, + node = mxmlFindElement(node, tree, "element", NULL, NULL, MXML_DESCEND)) { ... do something ... } -The `mxmlFindPath` function finds the (first) value node under a specific -element using a "path": +The `descend` argument \(`MXML_DESCEND` in the examples above) can be one of +three constants: - mxml_node_t *value = mxmlFindPath(tree, "path/to/*/foo/bar"); +- `MXML_NO_DESCEND`: ignore child nodes in the element hierarchy, instead using + siblings (same level) or parent nodes (above) until the top (root) node is + reached. -The `mxmlGetInteger`, `mxmlGetOpaque`, `mxmlGetReal`, and `mxmlGetText` -functions retrieve the value from a node: +- `MXML_DESCEND_FIRST`: start the search with the first child of the node, and + then search siblings. 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 previous example. + +- `MXML_DESCEND`: search child nodes first, then sibling nodes, and then parent + nodes. + + +## Iterating Nodes + +While the `mxmlFindNode` and `mxmlFindPath` functions will find a particular +element node, sometimes you need to iterate over all nodes. The `mxmlWalkNext` +and `mxmlWalkPrev` functions can be used to iterate through the XML node +tree: + + mxml_node_t * + mxmlWalkNext(mxml_node_t *node, mxml_node_t *top, + int descend); + + mxml_node_t * + mxmlWalkPrev(mxml_node_t *node, mxml_node_t *top, + int descend); + +Depending on the value of the `descend` argument, these functions will +automatically traverse child, sibling, and parent nodes until the `top` node is +reached. For example, the following code will iterate over all of the nodes in +the sample XML document in the previous section: mxml_node_t *node; - int intvalue = mxmlGetInteger(node); + for (node = xml; + node != NULL; + node = mxmlWalkNext(node, xml, MXML_DESCEND)) + { + ... do something ... + } - const char *opaquevalue = mxmlGetOpaque(node); +The nodes will be returned in the following order: - double realvalue = mxmlGetReal(node); + + + + val1 + + val2 + + val3 + + + val4 + + val5 + + val6 + + val7 + + val8 - int whitespacevalue; - const char *textvalue = mxmlGetText(node, &whitespacevalue); -Finally, once you are done with the XML data, use the `mxmlDelete` function to -recursively free the memory that is used for a particular node or the entire -tree: +## Indexing + +The `mxmlIndexNew` function allows you to create an index of nodes for faster +searching and enumeration: + + mxml_index_t * + mxmlIndexNew(mxml_node_t *node, const char *element, + const char *attr); + +The `element` and `attr` arguments control which elements are included in the +index. If `element` is not `NULL` then only elements with the specified name +are added to the index. Similarly, if `attr` is not `NULL` then only elements +containing the specified attribute are added to the index. The nodes are sorted +in the index. + +For example, the following code creates an index of all "id" values in an XML +document: + + mxml_index_t *ind = mxmlIndexNew(xml, NULL, "id"); + +Once the index is created, the `mxmlIndexFind` function can be used to find a +matching node: + + mxml_node_t * + mxmlIndexFind(mxml_index_t *ind, const char *element, + const char *value); + +For example, the following code will find the element whose "id" string is "42": + + mxml_node_t *node = mxmlIndexFind(ind, NULL, "42"); + +Alternately, the `mxmlIndexReset` and `mxmlIndexEnum` functions can be used to +enumerate the nodes in the index: + + mxml_node_t * + mxmlIndexReset(mxml_index_t *ind); + + mxml_node_t * + mxmlIndexEnum(mxml_index_t *ind); + +Typically these functions will be used in a `for` loop: + + mxml_node_t *node; + + for (node = mxmlIndexReset(ind); + node != NULL; + node = mxmlIndexEnum(ind)) + { + ... do something ... + } + +The `mxmlIndexCount` function returns the number of nodes in the index: + + int + mxmlIndexGetCount(mxml_index_t *ind); + +Finally, the `mxmlIndexDelete` function frees all memory associated with the +index: + + void + mxmlIndexDelete(mxml_index_t *ind); + + +# Custom Data Types + +Mini-XML supports custom data types via per-thread load and save callbacks. +Only a single set of callbacks can be active at any time for the current thread, +however your callbacks can store additional information in order to support +multiple custom data types as needed. The `MXML_CUSTOM` node type identifies +custom data nodes. + +The `mxmlGetCustom` function retrieves the custom value pointer for a node. + + const void * + mxmlGetCustom(mxml_node_t *node); + +Custom \(`MXML_CUSTOM`) nodes are created using the `mxmlNewCustom` function or +using a custom per-thread load callbacks specified using the +`mxmlSetCustomHandlers` function: - mxmlDelete(tree); + typedef void (*mxml_custom_destroy_cb_t)(void *); + typedef int (*mxml_custom_load_cb_t)(mxml_node_t *, const char *); + typedef char *(*mxml_custom_save_cb_t)(mxml_node_t *); + + mxml_node_t * + mxmlNewCustom(mxml_node_t *parent, void *data, + mxml_custom_destroy_cb_t destroy); + + int + mxmlSetCustom(mxml_node_t *node, void *data, + mxml_custom_destroy_cb_t destroy); + + void + mxmlSetCustomHandlers(mxml_custom_load_cb_t load, + mxml_custom_save_cb_t save); + +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: + + 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 > 60) + { + /* + * 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 (free) function + * pointers... + */ + + mxmlSetCustom(node, data, free); + + /* + * Return with no errors... + */ + + return (0); + } + +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 `void` +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. In this +example, we use the standard `free` function since everything is contained in a +single calloc'd block. + +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: + + 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)); + } + +You register the callback functions using the `mxmlSetCustomHandlers` function: + + mxmlSetCustomHandlers(load_custom, save_custom); + + +# SAX (Stream) Loading of Documents + +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. + +The `mxmlSAXLoadFd`, `mxmlSAXLoadFile`, and `mxmlSAXLoadString` functions +provide the SAX loading APIs: + + mxml_node_t * + mxmlSAXLoadFd(mxml_node_t *top, int fd, + mxml_type_t (*cb)(mxml_node_t *), + mxml_sax_cb_t sax, void *sax_data); + + mxml_node_t * + mxmlSAXLoadFile(mxml_node_t *top, FILE *fp, + mxml_type_t (*cb)(mxml_node_t *), + mxml_sax_cb_t sax, void *sax_data); + + mxml_node_t * + mxmlSAXLoadString(mxml_node_t *top, const char *s, + mxml_type_t (*cb)(mxml_node_t *), + mxml_sax_cb_t sax, 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 + sax_cb(mxml_node_t *node, mxml_sax_event_t event, + void *data) + { + ... do something ... + } + +The event will be one of the following: + +- `MXML_SAX_CDATA`: CDATA was just read. +- `MXML_SAX_COMMENT`: A comment was just read. +- `MXML_SAX_DATA`: Data (custom, integer, opaque, real, or text) was just read. +- `MXML_SAX_DIRECTIVE`: A processing directive/instruction was just read. +- `MXML_SAX_ELEMENT_CLOSE` - A close element was just read \(``) +- `MXML_SAX_ELEMENT_OPEN` - An open element was just read \(``) + +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 + sax_cb(mxml_node_t *node, mxml_sax_event_t event, + void *data) + { + if (event != MXML_SAX_ELEMENT_CLOSE) + mxmlRetain(node); + } + +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 ``, ``, and ``, and processing +directives like `` and ``: + + void + sax_cb(mxml_node_t *node, mxml_sax_event_t event, + void *data) + { + if (event == MXML_SAX_ELEMENT_OPEN) + { + /* + * Retain headings and titles... + */ + + const char *element = mxmlGetElement(node); + + if (!strcmp(element, "html") || + !strcmp(element, "head") || + !strcmp(element, "title") || + !strcmp(element, "body") || + !strcmp(element, "h1") || + !strcmp(element, "h2") || + !strcmp(element, "h3") || + !strcmp(element, "h4") || + !strcmp(element, "h5") || + !strcmp(element, "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); + } + } + } + +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: + + mxml_node_t *doc, *title, *body, *heading; + + doc = mxmlSAXLoadFd(NULL, 0, MXML_TEXT_CALLBACK, sax_cb, + 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); + } + +The `print_children` function is: + + void + print_children(mxml_node_t *parent) + { + mxml_node_t *node; + const char *text; + int whitespace; + + for (node = mxmlGetFirstChild(parent); + node != NULL; + node = mxmlGetNextSibling(node)) + { + text = mxmlGettext(node, &whitespace); + + if (whitespace) + putchar(' '); + + fputs(text, stdout); + } + + putchar('\n'); + } diff --git a/doc/mxml.man b/doc/mxml.man index 581b54d..f38f0a1 100644 --- a/doc/mxml.man +++ b/doc/mxml.man @@ -1,4 +1,4 @@ -.TH mxml 3 "Mini-XML API" "04/23/17" "Mini-XML API" +.TH mxml 3 "Mini-XML API" "04/24/17" "Mini-XML API" .SH NAME mxml \- Mini-XML API .SH INCLUDE FILE @@ -244,12 +244,12 @@ void mxmlAdd ( ); .fi .PP -Adds the specified node to the parent. If the child argument is not -NULL, puts the new node before or after the specified child depending -on the value of the where argument. If the child argument is NULL, -puts the new node at the beginning of the child list (MXML_ADD_BEFORE) -or at the end of the child list (MXML_ADD_AFTER). The constant -MXML_ADD_TO_PARENT can be used to specify a NULL child pointer. +Adds the specified node to the parent. If the child argument is not +\fBNULL\fR, puts the new node before or after the specified child depending +on the value of the where argument. If the child argument is \fBNULL\fR, +puts the new node at the beginning of the child list (\fBMXML_ADD_BEFORE\fR) +or at the end of the child list (\fBMXML_ADD_AFTER\fR). The constant +\fBMXML_ADD_TO_PARENT\fR can be used to specify a \fBNULL\fR child pointer. .SS mxmlDelete Delete a node and all of its children. .PP @@ -260,7 +260,7 @@ void mxmlDelete ( .fi .PP If the specified node has a parent, this function first removes the -node from its parent using the mxmlRemove() function. +node from its parent using the \fImxmlRemove\fR function. .SS mxmlElementDeleteAttr Delete an attribute. .PP @@ -282,7 +282,7 @@ const char * mxmlElementGetAttr ( ); .fi .PP -This function returns NULL if the node is not an element or the +This function returns \fBNULL\fR if the node is not an element or the named attribute does not exist. .SS mxmlElementGetAttrByIndex Get an element attribute by index. @@ -359,7 +359,7 @@ const char * mxmlEntityGetName ( ); .fi .PP -If val does not need to be represented by a named entity, NULL is returned. +If val does not need to be represented by a named entity, \fBNULL\fR is returned. .SS mxmlEntityGetValue Get the character corresponding to a named entity. .PP @@ -386,7 +386,7 @@ Find the named element. mxml_node_t * mxmlFindElement ( mxml_node_t *node, mxml_node_t *top, - const char *name, + const char *element, const char *attr, const char *value, int descend @@ -394,12 +394,12 @@ mxml_node_t * mxmlFindElement ( .fi .PP The search is constrained by the name, attribute name, and value; any -NULL names or values are treated as wildcards, so different kinds of +\fBNULL\fR names or values are treated as wildcards, so different kinds of searches can be implemented by looking for all elements of a given name or all elements with a specific attribute. The descend argument determines whether the search descends into child nodes; normally you will use -MXML_DESCEND_FIRST for the initial search and MXML_NO_DESCEND to find -additional direct descendents of the node. The top node argument +\fBMXML_DESCEND_FIRST\fR for the initial search and \fBMXML_NO_DESCEND\fR +to find additional direct descendents of the node. The top node argument constrains the search to a particular node's children. .SS mxmlFindPath Find a node with the given path. @@ -577,7 +577,7 @@ const char * mxmlGetText ( .fi .PP \fBNULL\fR is returned if the node (or its first child) is not a text node. -The "whitespace" argument can be NULL. +The "whitespace" argument can be \fBNULL\fR. .SS mxmlGetType @@ -619,7 +619,9 @@ mxml_node_t * mxmlIndexEnum ( ); .fi .PP -Nodes are returned in the sorted order of the index. +You should call \fImxmlIndexReset\fR prior to using this function to get +the first node in the index. Nodes are returned in the sorted order of the +index. .SS mxmlIndexFind Find the next matching node. .PP @@ -631,10 +633,10 @@ mxml_node_t * mxmlIndexFind ( ); .fi .PP -You should call mxmlIndexReset() prior to using this function for +You should call \fImxmlIndexReset\fR prior to using this function for the first time with a particular set of "element" and "value" -strings. Passing NULL for both "element" and "value" is equivalent -to calling mxmlIndexEnum(). +strings. Passing \fBNULL\fR for both "element" and "value" is equivalent +to calling \fImxmlIndexEnum\fR. .SS mxmlIndexGetCount Get the number of nodes in an index. .PP @@ -657,7 +659,7 @@ mxml_index_t * mxmlIndexNew ( .fi .PP The index will contain all nodes that contain the named element and/or -attribute. If both "element" and "attr" are NULL, then the index will +attribute. If both "element" and "attr" are \fBNULL\fR, then the index will contain a sorted list of the elements in the node tree. Nodes are sorted by element name and optionally by attribute value if the "attr" argument is not NULL. @@ -671,8 +673,8 @@ mxml_node_t * mxmlIndexReset ( ); .fi .PP -This function should be called prior to using mxmlIndexEnum() or -mxmlIndexFind() for the first time. +This function should be called prior to using \fImxmlIndexEnum\fR or +\fImxmlIndexFind\fR for the first time. .SS mxmlLoadFd Load a file descriptor into an XML node tree. .PP @@ -688,12 +690,9 @@ The nodes in the specified file are added to the specified top node. If no top node is provided, the XML file MUST be well-formed with a single parent node like for the entire file. The callback function returns the value type that should be used for child nodes. -If MXML_NO_CALLBACK is specified then all child nodes will be either -MXML_ELEMENT or MXML_TEXT nodes. -.PP -The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK, -MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading -child nodes of the specified type. +The constants \fBMXML_INTEGER_CALLBACK\fR, \fBMXML_OPAQUE_CALLBACK\fR, +\fBMXML_REAL_CALLBACK\fR, and \fBMXML_TEXT_CALLBACK\fR are defined for +loading child (data) nodes of the specified type. .SS mxmlLoadFile Load a file into an XML node tree. .PP @@ -709,12 +708,9 @@ The nodes in the specified file are added to the specified top node. If no top node is provided, the XML file MUST be well-formed with a single parent node like for the entire file. The callback function returns the value type that should be used for child nodes. -If MXML_NO_CALLBACK is specified then all child nodes will be either -MXML_ELEMENT or MXML_TEXT nodes. -.PP -The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK, -MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading -child nodes of the specified type. +The constants \fBMXML_INTEGER_CALLBACK\fR, \fBMXML_OPAQUE_CALLBACK\fR, +\fBMXML_REAL_CALLBACK\fR, and \fBMXML_TEXT_CALLBACK\fR are defined for +loading child (data) nodes of the specified type. .SS mxmlLoadString Load a string into an XML node tree. .PP @@ -730,12 +726,9 @@ The nodes in the specified string are added to the specified top node. If no top node is provided, the XML string MUST be well-formed with a single parent node like for the entire string. The callback function returns the value type that should be used for child nodes. -If MXML_NO_CALLBACK is specified then all child nodes will be either -MXML_ELEMENT or MXML_TEXT nodes. -.PP -The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK, -MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading -child nodes of the specified type. +The constants \fBMXML_INTEGER_CALLBACK\fR, \fBMXML_OPAQUE_CALLBACK\fR, +\fBMXML_REAL_CALLBACK\fR, and \fBMXML_TEXT_CALLBACK\fR are defined for +loading child (data) nodes of the specified type. .SS mxmlNewCDATA Create a new CDATA node. .PP @@ -747,9 +740,10 @@ mxml_node_t * mxmlNewCDATA ( .fi .PP The new CDATA node is added to the end of the specified parent's child -list. The constant MXML_NO_PARENT can be used to specify that the new -CDATA node has no parent. The data string must be nul-terminated and -is copied into the new node. CDATA nodes use the MXML_ELEMENT type. +list. The constant \fBMXML_NO_PARENT\fR can be used to specify that the new +CDATA node has no parent. The data string must be nul-terminated and +is copied into the new node. CDATA nodes currently use the +\fBMXML_ELEMENT\fR type. .SS mxmlNewCustom @@ -764,8 +758,8 @@ mxml_node_t * mxmlNewCustom ( .fi .PP The new custom node is added to the end of the specified parent's child -list. The constant MXML_NO_PARENT can be used to specify that the new -element node has no parent. NULL can be passed when the data in the +list. The constant \fBMXML_NO_PARENT\fR can be used to specify that the new +element node has no parent. \fBNULL\fR can be passed when the data in the node is not dynamically allocated or is separately managed. @@ -780,7 +774,7 @@ mxml_node_t * mxmlNewElement ( .fi .PP The new element node is added to the end of the specified parent's child -list. The constant MXML_NO_PARENT can be used to specify that the new +list. The constant \fBMXML_NO_PARENT\fR can be used to specify that the new element node has no parent. .SS mxmlNewInteger Create a new integer node. @@ -793,7 +787,7 @@ mxml_node_t * mxmlNewInteger ( .fi .PP The new integer node is added to the end of the specified parent's child -list. The constant MXML_NO_PARENT can be used to specify that the new +list. The constant \fBMXML_NO_PARENT\fR can be used to specify that the new integer node has no parent. .SS mxmlNewOpaque Create a new opaque string. @@ -805,10 +799,25 @@ mxml_node_t * mxmlNewOpaque ( ); .fi .PP -The new opaque node is added to the end of the specified parent's child -list. The constant MXML_NO_PARENT can be used to specify that the new -opaque node has no parent. The opaque string must be nul-terminated and -is copied into the new node. +The new opaque string node is added to the end of the specified parent's +child list. The constant \fBMXML_NO_PARENT\fR can be used to specify that +the new opaque string node has no parent. The opaque string must be nul- +terminated and is copied into the new node. +.SS mxmlNewOpaquef +Create a new formatted opaque string node. +.PP +.nf +mxml_node_t * mxmlNewOpaquef ( + mxml_node_t *parent, + const char *format, + ... +); +.fi +.PP +The new opaque string node is added to the end of the specified parent's +child list. The constant \fBMXML_NO_PARENT\fR can be used to specify that +the new opaque string node has no parent. The format string must be +nul-terminated and is formatted into the new node. .SS mxmlNewReal Create a new real number node. .PP @@ -820,7 +829,7 @@ mxml_node_t * mxmlNewReal ( .fi .PP The new real number node is added to the end of the specified parent's -child list. The constant MXML_NO_PARENT can be used to specify that +child list. The constant \fBMXML_NO_PARENT\fR can be used to specify that the new real number node has no parent. .SS mxmlNewText Create a new text fragment node. @@ -834,9 +843,9 @@ mxml_node_t * mxmlNewText ( .fi .PP The new text node is added to the end of the specified parent's child -list. The constant MXML_NO_PARENT can be used to specify that the new -text node has no parent. The whitespace parameter is used to specify -whether leading whitespace is present before the node. The text +list. The constant \fBMXML_NO_PARENT\fR can be used to specify that the new +text node has no parent. The whitespace parameter is used to specify +whether leading whitespace is present before the node. The text string must be nul-terminated and is copied into the new node. .SS mxmlNewTextf Create a new formatted text fragment node. @@ -851,9 +860,9 @@ mxml_node_t * mxmlNewTextf ( .fi .PP The new text node is added to the end of the specified parent's child -list. The constant MXML_NO_PARENT can be used to specify that the new -text node has no parent. The whitespace parameter is used to specify -whether leading whitespace is present before the node. The format +list. The constant \fBMXML_NO_PARENT\fR can be used to specify that the new +text node has no parent. The whitespace parameter is used to specify +whether leading whitespace is present before the node. The format string must be nul-terminated and is formatted into the new node. .SS mxmlNewXML Create a new XML document tree. @@ -865,7 +874,7 @@ mxml_node_t * mxmlNewXML ( .fi .PP The "version" argument specifies the version number to put in the -?xml element node. If NULL, version 1.0 is assumed. +?xml element node. If \fBNULL\fR, version "1.0" is assumed. .SS mxmlRelease @@ -878,7 +887,7 @@ int mxmlRelease ( .fi .PP When the reference count reaches zero, the node (and any children) -is deleted via mxmlDelete(). +is deleted via \fImxmlDelete\fR. .SS mxmlRemove @@ -890,8 +899,8 @@ void mxmlRemove ( ); .fi .PP -Does not free memory used by the node - use mxmlDelete() for that. -This function does nothing if the node has no parent. +This function does not free memory used by the node - use \fImxmlDelete\fR +for that. This function does nothing if the node has no parent. .SS mxmlRetain Retain a node. .PP @@ -920,14 +929,11 @@ The nodes in the specified file are added to the specified top node. If no top node is provided, the XML file MUST be well-formed with a single parent node like for the entire file. The callback function returns the value type that should be used for child nodes. -If MXML_NO_CALLBACK is specified then all child nodes will be either -MXML_ELEMENT or MXML_TEXT nodes. -.PP -The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK, -MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading -child nodes of the specified type. +The constants \fBMXML_INTEGER_CALLBACK\fR, \fBMXML_OPAQUE_CALLBACK\fR, +\fBMXML_REAL_CALLBACK\fR, and \fBMXML_TEXT_CALLBACK\fR are defined for +loading child nodes of the specified type. .PP -The SAX callback must call mxmlRetain() for any nodes that need to +The SAX callback must call \fImxmlRetain\fR for any nodes that need to be kept for later use. Otherwise, nodes are deleted when the parent node is closed or after each data, comment, CDATA, or directive node. @@ -950,14 +956,11 @@ The nodes in the specified file are added to the specified top node. If no top node is provided, the XML file MUST be well-formed with a single parent node like for the entire file. The callback function returns the value type that should be used for child nodes. -If MXML_NO_CALLBACK is specified then all child nodes will be either -MXML_ELEMENT or MXML_TEXT nodes. +The constants \fBMXML_INTEGER_CALLBACK\fR, \fBMXML_OPAQUE_CALLBACK\fR, +\fBMXML_REAL_CALLBACK\fR, and \fBMXML_TEXT_CALLBACK\fR are defined for +loading child nodes of the specified type. .PP -The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK, -MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading -child nodes of the specified type. -.PP -The SAX callback must call mxmlRetain() for any nodes that need to +The SAX callback must call \fImxmlRetain\fR for any nodes that need to be kept for later use. Otherwise, nodes are deleted when the parent node is closed or after each data, comment, CDATA, or directive node. @@ -980,14 +983,11 @@ The nodes in the specified string are added to the specified top node. If no top node is provided, the XML string MUST be well-formed with a single parent node like for the entire string. The callback function returns the value type that should be used for child nodes. -If MXML_NO_CALLBACK is specified then all child nodes will be either -MXML_ELEMENT or MXML_TEXT nodes. -.PP -The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK, -MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading -child nodes of the specified type. +The constants \fBMXML_INTEGER_CALLBACK\fR, \fBMXML_OPAQUE_CALLBACK\fR, +\fBMXML_REAL_CALLBACK\fR, and \fBMXML_TEXT_CALLBACK\fR are defined for +loading child nodes of the specified type. .PP -The SAX callback must call mxmlRetain() for any nodes that need to +The SAX callback must call \fImxmlRetain\fR for any nodes that need to be kept for later use. Otherwise, nodes are deleted when the parent node is closed or after each data, comment, CDATA, or directive node. @@ -1004,13 +1004,13 @@ char * mxmlSaveAllocString ( .PP This function returns a pointer to a string containing the textual representation of the XML node tree. The string should be freed -using the free() function when you are done with it. NULL is returned +using the free() function when you are done with it. \fBNULL\fR is returned if the node would produce an empty string or if the string cannot be allocated. .PP The callback argument specifies a function that returns a whitespace -string or NULL before and after each element. If MXML_NO_CALLBACK -is specified, whitespace will only be added before MXML_TEXT nodes +string or NULL before and after each element. If \fBMXML_NO_CALLBACK\fR +is specified, whitespace will only be added before \fBMXML_TEXT\fR nodes with leading whitespace and before attribute names inside opening element tags. .SS mxmlSaveFd @@ -1025,8 +1025,8 @@ int mxmlSaveFd ( .fi .PP The callback argument specifies a function that returns a whitespace -string or NULL before and after each element. If MXML_NO_CALLBACK -is specified, whitespace will only be added before MXML_TEXT nodes +string or NULL before and after each element. If \fBMXML_NO_CALLBACK\fR +is specified, whitespace will only be added before \fBMXML_TEXT\fR nodes with leading whitespace and before attribute names inside opening element tags. .SS mxmlSaveFile @@ -1041,8 +1041,8 @@ int mxmlSaveFile ( .fi .PP The callback argument specifies a function that returns a whitespace -string or NULL before and after each element. If MXML_NO_CALLBACK -is specified, whitespace will only be added before MXML_TEXT nodes +string or NULL before and after each element. If \fBMXML_NO_CALLBACK\fR +is specified, whitespace will only be added before \fBMXML_TEXT\fR nodes with leading whitespace and before attribute names inside opening element tags. .SS mxmlSaveString @@ -1062,8 +1062,8 @@ required for the string but only copies (bufsize - 1) characters into the specified buffer. .PP The callback argument specifies a function that returns a whitespace -string or NULL before and after each element. If MXML_NO_CALLBACK -is specified, whitespace will only be added before MXML_TEXT nodes +string or NULL before and after each element. If \fBMXML_NO_CALLBACK\fR +is specified, whitespace will only be added before \fBMXML_TEXT\fR nodes with leading whitespace and before attribute names inside opening element tags. .SS mxmlSetCDATA @@ -1107,7 +1107,7 @@ 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 NULL on error. +string on success and \fBNULL\fR on error. .SS mxmlSetElement Set the name of an element node. .PP @@ -1149,6 +1149,20 @@ int mxmlSetOpaque ( .fi .PP The node is not changed if it (or its first child) is not an opaque node. +.SS mxmlSetOpaquef +Set the value of an opaque string node to a formatted string. +.PP +.nf +int mxmlSetOpaquef ( + mxml_node_t *node, + const char *format, + ... +); +.fi +.PP +The node is not changed if it (or its first child) is not an opaque node. + + .SS mxmlSetReal Set the value of a real number node. .PP @@ -1220,7 +1234,7 @@ mxml_node_t * mxmlWalkNext ( .fi .PP The descend argument controls whether the first child is considered -to be the next node. The top node argument constrains the walk to +to be the next node. The top node argument constrains the walk to the node's children. .SS mxmlWalkPrev Walk to the previous logical node in the tree. @@ -1234,7 +1248,7 @@ mxml_node_t * mxmlWalkPrev ( .fi .PP The descend argument controls whether the previous node's last child -is considered to be the previous node. The top node argument constrains +is considered to be the previous node. The top node argument constrains the walk to the node's children. .SH TYPES .SS mxml_custom_destroy_cb_t diff --git a/doc/reference.html b/doc/reference.html index ea4f62c..7321000 100644 --- a/doc/reference.html +++ b/doc/reference.html @@ -85,11 +85,20 @@ div.contents ul.contents { } .variable { } +blockquote { + border: solid thin gray; + box-shadow: 3px 3px 5px rgba(0,0,0,0.5); + padding: 0px 10px; + page-break-inside: avoid; +} p code, li code, p.code, pre, ul.code li { background: rgba(127,127,127,0.1); border: thin dotted gray; font-family: monospace; font-size: 90%; + hyphens: manual; + -webkit-hyphens: manual; + page-break-inside: avoid; } p.code, pre, ul.code li { padding: 10px; @@ -196,6 +205,7 @@ h3.title {
  • mxmlNewElement
  • mxmlNewInteger
  • mxmlNewOpaque
  • +
  • mxmlNewOpaquef
  • mxmlNewReal
  • mxmlNewText
  • mxmlNewTextf
  • @@ -217,6 +227,7 @@ h3.title {
  • mxmlSetErrorCallback
  • mxmlSetInteger
  • mxmlSetOpaque
  • +
  • mxmlSetOpaquef
  • mxmlSetReal
  • mxmlSetText
  • mxmlSetTextf
  • @@ -261,19 +272,12 @@ void mxmlAdd (
    parent
    Parent node
    where
    -
    Where to add, MXML_ADD_BEFORE or MXML_ADD_AFTER
    +
    Where to add, MXML_ADD_BEFORE or MXML_ADD_AFTER
    child
    -
    Child node for where or MXML_ADD_TO_PARENT
    +
    Child node for where or MXML_ADD_TO_PARENT
    node
    Node to add
    -

    Discussion

    -

    Adds the specified node to the parent. If the child argument is not -NULL, puts the new node before or after the specified child depending -on the value of the where argument. If the child argument is NULL, -puts the new node at the beginning of the child list (MXML_ADD_BEFORE) -or at the end of the child list (MXML_ADD_AFTER). The constant -MXML_ADD_TO_PARENT can be used to specify a NULL child pointer.

    mxmlDelete

    Delete a node and all of its children.

    @@ -285,9 +289,6 @@ void mxmlDelete (

    node
    Node to delete
    -

    Discussion

    -

    If the specified node has a parent, this function first removes the -node from its parent using the mxmlRemove() function.

     Mini-XML 2.4 mxmlElementDeleteAttr

    Delete an attribute.

    @@ -317,10 +318,7 @@ const char *mxmlElementGetAttr (

    Name of attribute

    Return Value

    -

    Attribute value or NULL

    -

    Discussion

    -

    This function returns NULL if the node is not an element or the -named attribute does not exist.

    +

    Attribute value or NULL

     Mini-XML 2.11 mxmlElementGetAttrByIndex

    Get an element attribute by index.

    @@ -340,11 +338,6 @@ const char *mxmlElementGetAttrByIndex (

    Return Value

    Attribute value

    -

    Discussion

    -

    The index ("idx") is 0-based. NULL is returned if the specified index -is out of range. - -

     Mini-XML 2.11 mxmlElementGetAttrCount

    Get the number of element attributes.

    @@ -375,11 +368,6 @@ void mxmlElementSetAttr (

    value
    Attribute value
    -

    Discussion

    -

    If the named attribute already exists, the value of the attribute -is replaced by the new string value. The string value is copied -into the element node. This function does nothing if the node is -not an element.

     Mini-XML 2.3 mxmlElementSetAttrf

    Set an attribute with a formatted value.

    @@ -400,13 +388,6 @@ void mxmlElementSetAttrf (

    ...
    Additional arguments as needed
    -

    Discussion

    -

    If the named attribute already exists, the value of the attribute -is replaced by the new formatted string. The formatted string value is -copied into the element node. This function does nothing if the node -is not an element. - -

    mxmlEntityAddCallback

    Add a callback to convert entities to Unicode.

    @@ -432,9 +413,7 @@ const char *mxmlEntityGetName (

    Character value

    Return Value

    -

    Entity name or NULL

    -

    Discussion

    -

    If val does not need to be represented by a named entity, NULL is returned.

    +

    Entity name or NULL

    mxmlEntityGetValue

    Get the character corresponding to a named entity.

    @@ -448,9 +427,6 @@ int mxmlEntityGetValue (

    Return Value

    Character value or -1 on error

    -

    Discussion

    -

    The entity name can also be a numeric constant. -1 is returned if the -name is not known.

    mxmlEntityRemoveCallback

    Remove a callback.

    @@ -468,7 +444,7 @@ void mxmlEntityRemoveCallback (
    mxml_node_t *mxmlFindElement (
        mxml_node_t *node,
        mxml_node_t *top,
    -    const char *name,
    +    const char *element,
        const char *attr,
        const char *value,
        int descend
    @@ -479,26 +455,17 @@ void mxmlEntityRemoveCallback (

    Current node
    top
    Top node
    -
    name
    -
    Element name or NULL for any
    +
    element
    +
    Element name or NULL for any
    attr
    -
    Attribute name, or NULL for none
    +
    Attribute name, or NULL for none
    value
    -
    Attribute value, or NULL for any
    +
    Attribute value, or NULL for any
    descend
    -
    Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST
    +
    Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST

    Return Value

    -

    Element node or NULL

    -

    Discussion

    -

    The search is constrained by the name, attribute name, and value; any -NULL names or values are treated as wildcards, so different kinds of -searches can be implemented by looking for all elements of a given name -or all elements with a specific attribute. The descend argument determines -whether the search descends into child nodes; normally you will use -MXML_DESCEND_FIRST for the initial search and MXML_NO_DESCEND to find -additional direct descendents of the node. The top node argument -constrains the search to a particular node's children.

    +

    Element node or NULL

     Mini-XML 2.7 mxmlFindPath

    Find a node with the given path.

    @@ -514,16 +481,7 @@ constrains the search to a particular node's children.

    Path to element

    Return Value

    -

    Found node or NULL

    -

    Discussion

    -

    The "path" is a slash-separated list of element names. The name "*" is -considered a wildcard for one or more levels of elements. For example, -"foo/one/two", "bar/two/one", "*/one", and so forth.
    -
    -The first child node of the found node is returned if the given node has -children and the first child is a value node. - -

    +

    Found node or NULL

     Mini-XML 2.7 mxmlGetCDATA

    Get the value for a CDATA node.

    @@ -536,11 +494,7 @@ const char *mxmlGetCDATA (

    Node to get

    Return Value

    -

    CDATA value or NULL

    -

    Discussion

    -

    NULL is returned if the node is not a CDATA element. - -

    +

    CDATA value or NULL

     Mini-XML 2.7 mxmlGetCustom

    Get the value for a custom node.

    @@ -553,12 +507,7 @@ const void *mxmlGetCustom (

    Node to get

    Return Value

    -

    Custom value or NULL

    -

    Discussion

    -

    NULL is returned if the node (or its first child) is not a custom -value node. - -

    +

    Custom value or NULL

     Mini-XML 2.7 mxmlGetElement

    Get the name for an element node.

    @@ -571,11 +520,7 @@ const char *mxmlGetElement (

    Node to get

    Return Value

    -

    Element name or NULL

    -

    Discussion

    -

    NULL is returned if the node is not an element node. - -

    +

    Element name or NULL

     Mini-XML 2.7 mxmlGetFirstChild

    Get the first child of an element node.

    @@ -588,12 +533,7 @@ const char *mxmlGetElement (

    Node to get

    Return Value

    -

    First child or NULL

    -

    Discussion

    -

    NULL is returned if the node is not an element node or if the node -has no children. - -

    +

    First child or NULL

     Mini-XML 2.7 mxmlGetInteger

    Get the integer value from the specified node or its first child.

    @@ -608,10 +548,6 @@ int mxmlGetInteger (

    Return Value

    Integer value or 0

    -

    Discussion

    -

    0 is returned if the node (or its first child) is not an integer value node. - -

     Mini-XML 2.7 mxmlGetLastChild

    Get the last child of an element node.

    @@ -624,12 +560,7 @@ int mxmlGetInteger (

    Node to get

    Return Value

    -

    Last child or NULL

    -

    Discussion

    -

    NULL is returned if the node is not an element node or if the node -has no children. - -

    +

    Last child or NULL

    mxmlGetNextSibling

    Return the node type...

    @@ -658,12 +589,7 @@ const char *mxmlGetOpaque (

    Node to get

    Return Value

    -

    Opaque string or NULL

    -

    Discussion

    -

    NULL is returned if the node (or its first child) is not an opaque -value node. - -

    +

    Opaque string or NULL

     Mini-XML 2.7 mxmlGetParent

    Get the parent node.

    @@ -676,11 +602,7 @@ value node.

    Node to get

    Return Value

    -

    Parent node or NULL

    -

    Discussion

    -

    NULL is returned for a root node. - -

    +

    Parent node or NULL

     Mini-XML 2.7 mxmlGetPrevSibling

    Get the previous node for the current parent.

    @@ -693,11 +615,7 @@ value node.

    Node to get

    Return Value

    -

    Previous node or NULL

    -

    Discussion

    -

    NULL is returned if this is the first child for the current parent. - -

    +

    Previous node or NULL

     Mini-XML 2.7 mxmlGetReal

    Get the real value for a node or its first child.

    @@ -711,10 +629,6 @@ double mxmlGetReal (

    Return Value

    Real value or 0.0

    -

    Discussion

    -

    0.0 is returned if the node (or its first child) is not a real value node. - -

     Mini-XML 2.7 mxmlGetRefCount

    Get the current reference (use) count for a node.

    @@ -728,12 +642,6 @@ int mxmlGetRefCount (

    Return Value

    Reference count

    -

    Discussion

    -

    The initial reference count of new nodes is 1. Use the mxmlRetain -and mxmlRelease functions to increment and decrement a node's -reference count. - -.

     Mini-XML 2.7 mxmlGetText

    Get the text value for a node or its first child.

    @@ -749,12 +657,7 @@ const char *mxmlGetText (

    1 if string is preceded by whitespace, 0 otherwise

    Return Value

    -

    Text string or NULL

    -

    Discussion

    -

    NULL is returned if the node (or its first child) is not a text node. -The "whitespace" argument can be NULL. - -

    +

    Text string or NULL

     Mini-XML 2.7 mxmlGetType

    Get the node type.

    @@ -768,10 +671,6 @@ The "whitespace" argument can be NULL.

    Return Value

    Type of node

    -

    Discussion

    -

    MXML_IGNORE is returned if "node" is NULL. - -

     Mini-XML 2.7 mxmlGetUserData

    Get the user data pointer for a node.

    @@ -808,9 +707,7 @@ void mxmlIndexDelete (

    Index to enumerate

    Return Value

    -

    Next node or NULL if there is none

    -

    Discussion

    -

    Nodes are returned in the sorted order of the index.

    +

    Next node or NULL if there is none

    mxmlIndexFind

    Find the next matching node.

    @@ -829,12 +726,7 @@ void mxmlIndexDelete (

    Attribute value, if any

    Return Value

    -

    Node or NULL if none found

    -

    Discussion

    -

    You should call mxmlIndexReset() prior to using this function for -the first time with a particular set of "element" and "value" -strings. Passing NULL for both "element" and "value" is equivalent -to calling mxmlIndexEnum().

    +

    Node or NULL if none found

     Mini-XML 2.7 mxmlIndexGetCount

    Get the number of nodes in an index.

    @@ -861,18 +753,12 @@ int mxmlIndexGetCount (

    node
    XML node tree
    element
    -
    Element to index or NULL for all
    +
    Element to index or NULL for all
    attr
    -
    Attribute to index or NULL for none
    +
    Attribute to index or NULL for none

    Return Value

    New index

    -

    Discussion

    -

    The index will contain all nodes that contain the named element and/or -attribute. If both "element" and "attr" are NULL, then the index will -contain a sorted list of the elements in the node tree. Nodes are -sorted by element name and optionally by attribute value if the "attr" -argument is not NULL.

    mxmlIndexReset

    Reset the enumeration/find pointer in the index and return the first node in the index.

    @@ -886,10 +772,7 @@ return the first node in the index.

    Index to reset

    Return Value

    -

    First node or NULL if there is none

    -

    Discussion

    -

    This function should be called prior to using mxmlIndexEnum() or -mxmlIndexFind() for the first time.

    +

    First node or NULL if there is none

    mxmlLoadFd

    Load a file descriptor into an XML node tree.

    @@ -905,21 +788,10 @@ mxmlIndexFind() for the first time.

    fd
    File descriptor to read from
    cb
    -
    Callback function or MXML_NO_CALLBACK
    +
    Callback function or constant

    Return Value

    -

    First node or NULL if the file could not be read.

    -

    Discussion

    -

    The nodes in the specified file are added to the specified top node. -If no top node is provided, the XML file MUST be well-formed with a -single parent node like <?xml> for the entire file. The callback -function returns the value type that should be used for child nodes. -If MXML_NO_CALLBACK is specified then all child nodes will be either -MXML_ELEMENT or MXML_TEXT nodes.
    -
    -The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK, -MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading -child nodes of the specified type.

    +

    First node or NULL if the file could not be read.

    mxmlLoadFile

    Load a file into an XML node tree.

    @@ -935,21 +807,10 @@ child nodes of the specified type.

    fp
    File to read from
    cb
    -
    Callback function or MXML_NO_CALLBACK
    +
    Callback function or constant

    Return Value

    -

    First node or NULL if the file could not be read.

    -

    Discussion

    -

    The nodes in the specified file are added to the specified top node. -If no top node is provided, the XML file MUST be well-formed with a -single parent node like <?xml> for the entire file. The callback -function returns the value type that should be used for child nodes. -If MXML_NO_CALLBACK is specified then all child nodes will be either -MXML_ELEMENT or MXML_TEXT nodes.
    -
    -The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK, -MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading -child nodes of the specified type.

    +

    First node or NULL if the file could not be read.

    mxmlLoadString

    Load a string into an XML node tree.

    @@ -965,21 +826,10 @@ child nodes of the specified type.

    s
    String to load
    cb
    -
    Callback function or MXML_NO_CALLBACK
    +
    Callback function or constant

    Return Value

    -

    First node or NULL if the string has errors.

    -

    Discussion

    -

    The nodes in the specified string are added to the specified top node. -If no top node is provided, the XML string MUST be well-formed with a -single parent node like <?xml> for the entire string. The callback -function returns the value type that should be used for child nodes. -If MXML_NO_CALLBACK is specified then all child nodes will be either -MXML_ELEMENT or MXML_TEXT nodes.
    -
    -The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK, -MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading -child nodes of the specified type.

    +

    First node or NULL if the string has errors.

     Mini-XML 2.3 mxmlNewCDATA

    Create a new CDATA node.

    @@ -990,19 +840,12 @@ child nodes of the specified type.

    Parameters

    parent
    -
    Parent node or MXML_NO_PARENT
    +
    Parent node or MXML_NO_PARENT
    data
    Data string

    Return Value

    New node

    -

    Discussion

    -

    The new CDATA node is added to the end of the specified parent's child -list. The constant MXML_NO_PARENT can be used to specify that the new -CDATA node has no parent. The data string must be nul-terminated and -is copied into the new node. CDATA nodes use the MXML_ELEMENT type. - -

     Mini-XML 2.1 mxmlNewCustom

    Create a new custom data node.

    @@ -1014,7 +857,7 @@ is copied into the new node. CDATA nodes use the MXML_ELEMENT type.

    Parameters

    parent
    -
    Parent node or MXML_NO_PARENT
    +
    Parent node or MXML_NO_PARENT
    data
    Pointer to data
    destroy
    @@ -1022,13 +865,6 @@ is copied into the new node. CDATA nodes use the MXML_ELEMENT type.

    Return Value

    New node

    -

    Discussion

    -

    The new custom node is added to the end of the specified parent's child -list. The constant MXML_NO_PARENT can be used to specify that the new -element node has no parent. NULL can be passed when the data in the -node is not dynamically allocated or is separately managed. - -

    mxmlNewElement

    Create a new element node.

    @@ -1039,16 +875,12 @@ node is not dynamically allocated or is separately managed.

    Parameters

    parent
    -
    Parent node or MXML_NO_PARENT
    +
    Parent node or MXML_NO_PARENT
    name
    Name of element

    Return Value

    New node

    -

    Discussion

    -

    The new element node is added to the end of the specified parent's child -list. The constant MXML_NO_PARENT can be used to specify that the new -element node has no parent.

    mxmlNewInteger

    Create a new integer node.

    @@ -1059,16 +891,12 @@ element node has no parent.

    Parameters

    parent
    -
    Parent node or MXML_NO_PARENT
    +
    Parent node or MXML_NO_PARENT
    integer
    Integer value

    Return Value

    New node

    -

    Discussion

    -

    The new integer node is added to the end of the specified parent's child -list. The constant MXML_NO_PARENT can be used to specify that the new -integer node has no parent.

    mxmlNewOpaque

    Create a new opaque string.

    @@ -1079,17 +907,31 @@ integer node has no parent.

    Parameters

    parent
    -
    Parent node or MXML_NO_PARENT
    +
    Parent node or MXML_NO_PARENT
    opaque
    Opaque string

    Return Value

    New node

    -

    Discussion

    -

    The new opaque node is added to the end of the specified parent's child -list. The constant MXML_NO_PARENT can be used to specify that the new -opaque node has no parent. The opaque string must be nul-terminated and -is copied into the new node.

    +

    mxmlNewOpaquef

    +

    Create a new formatted opaque string node.

    +

    +mxml_node_t *mxmlNewOpaquef (
    +    mxml_node_t *parent,
    +    const char *format,
    +    ...
    +);

    +

    Parameters

    +
    +
    parent
    +
    Parent node or MXML_NO_PARENT
    +
    format
    +
    Printf-style format string
    +
    ...
    +
    Additional args as needed
    +
    +

    Return Value

    +

    New node

    mxmlNewReal

    Create a new real number node.

    @@ -1100,16 +942,12 @@ is copied into the new node.

    Parameters

    parent
    -
    Parent node or MXML_NO_PARENT
    +
    Parent node or MXML_NO_PARENT
    real
    Real number value

    Return Value

    New node

    -

    Discussion

    -

    The new real number node is added to the end of the specified parent's -child list. The constant MXML_NO_PARENT can be used to specify that -the new real number node has no parent.

    mxmlNewText

    Create a new text fragment node.

    @@ -1121,7 +959,7 @@ the new real number node has no parent.

    Parameters

    parent
    -
    Parent node or MXML_NO_PARENT
    +
    Parent node or MXML_NO_PARENT
    whitespace
    1 = leading whitespace, 0 = no whitespace
    string
    @@ -1129,12 +967,6 @@ the new real number node has no parent.

    Return Value

    New node

    -

    Discussion

    -

    The new text node is added to the end of the specified parent's child -list. The constant MXML_NO_PARENT can be used to specify that the new -text node has no parent. The whitespace parameter is used to specify -whether leading whitespace is present before the node. The text -string must be nul-terminated and is copied into the new node.

    mxmlNewTextf

    Create a new formatted text fragment node.

    @@ -1147,22 +979,16 @@ string must be nul-terminated and is copied into the new node.

    Parameters

    parent
    -
    Parent node or MXML_NO_PARENT
    +
    Parent node or MXML_NO_PARENT
    whitespace
    1 = leading whitespace, 0 = no whitespace
    format
    -
    Printf-style frmat string
    +
    Printf-style format string
    ...
    Additional args as needed

    Return Value

    New node

    -

    Discussion

    -

    The new text node is added to the end of the specified parent's child -list. The constant MXML_NO_PARENT can be used to specify that the new -text node has no parent. The whitespace parameter is used to specify -whether leading whitespace is present before the node. The format -string must be nul-terminated and is formatted into the new node.

     Mini-XML 2.3 mxmlNewXML

    Create a new XML document tree.

    @@ -1176,11 +1002,6 @@ string must be nul-terminated and is formatted into the new node.

    Return Value

    New ?xml node

    -

    Discussion

    -

    The "version" argument specifies the version number to put in the -?xml element node. If NULL, version 1.0 is assumed. - -

     Mini-XML 2.3 mxmlRelease

    Release a node.

    @@ -1194,11 +1015,6 @@ int mxmlRelease (

    Return Value

    New reference count

    -

    Discussion

    -

    When the reference count reaches zero, the node (and any children) -is deleted via mxmlDelete(). - -

    mxmlRemove

    Remove a node from its parent.

    @@ -1210,9 +1026,6 @@ void mxmlRemove (

    node
    Node to remove
    -

    Discussion

    -

    Does not free memory used by the node - use mxmlDelete() for that. -This function does nothing if the node has no parent.

     Mini-XML 2.3 mxmlRetain

    Retain a node.

    @@ -1244,31 +1057,14 @@ using a SAX callback.

    fd
    File descriptor to read from
    cb
    -
    Callback function or MXML_NO_CALLBACK
    +
    Callback function or constant
    sax_cb
    -
    SAX callback or MXML_NO_CALLBACK
    +
    SAX callback or MXML_NO_CALLBACK
    sax_data
    SAX user data

    Return Value

    -

    First node or NULL if the file could not be read.

    -

    Discussion

    -

    The nodes in the specified file are added to the specified top node. -If no top node is provided, the XML file MUST be well-formed with a -single parent node like <?xml> for the entire file. The callback -function returns the value type that should be used for child nodes. -If MXML_NO_CALLBACK is specified then all child nodes will be either -MXML_ELEMENT or MXML_TEXT nodes.
    -
    -The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK, -MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading -child nodes of the specified type.
    -
    -The SAX callback must call mxmlRetain() for any nodes that need to -be kept for later use. Otherwise, nodes are deleted when the parent -node is closed or after each data, comment, CDATA, or directive node. - -

    +

    First node or NULL if the file could not be read.

     Mini-XML 2.3 mxmlSAXLoadFile

    Load a file into an XML node tree using a SAX callback.

    @@ -1287,31 +1083,14 @@ using a SAX callback.

    fp
    File to read from
    cb
    -
    Callback function or MXML_NO_CALLBACK
    +
    Callback function or constant
    sax_cb
    -
    SAX callback or MXML_NO_CALLBACK
    +
    SAX callback or MXML_NO_CALLBACK
    sax_data
    SAX user data

    Return Value

    -

    First node or NULL if the file could not be read.

    -

    Discussion

    -

    The nodes in the specified file are added to the specified top node. -If no top node is provided, the XML file MUST be well-formed with a -single parent node like <?xml> for the entire file. The callback -function returns the value type that should be used for child nodes. -If MXML_NO_CALLBACK is specified then all child nodes will be either -MXML_ELEMENT or MXML_TEXT nodes.
    -
    -The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK, -MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading -child nodes of the specified type.
    -
    -The SAX callback must call mxmlRetain() for any nodes that need to -be kept for later use. Otherwise, nodes are deleted when the parent -node is closed or after each data, comment, CDATA, or directive node. - -

    +

    First node or NULL if the file could not be read.

     Mini-XML 2.3 mxmlSAXLoadString

    Load a string into an XML node tree using a SAX callback.

    @@ -1330,31 +1109,14 @@ using a SAX callback.

    s
    String to load
    cb
    -
    Callback function or MXML_NO_CALLBACK
    +
    Callback function or constant
    sax_cb
    -
    SAX callback or MXML_NO_CALLBACK
    +
    SAX callback or MXML_NO_CALLBACK
    sax_data
    SAX user data

    Return Value

    -

    First node or NULL if the string has errors.

    -

    Discussion

    -

    The nodes in the specified string are added to the specified top node. -If no top node is provided, the XML string MUST be well-formed with a -single parent node like <?xml> for the entire string. The callback -function returns the value type that should be used for child nodes. -If MXML_NO_CALLBACK is specified then all child nodes will be either -MXML_ELEMENT or MXML_TEXT nodes.
    -
    -The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK, -MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading -child nodes of the specified type.
    -
    -The SAX callback must call mxmlRetain() for any nodes that need to -be kept for later use. Otherwise, nodes are deleted when the parent -node is closed or after each data, comment, CDATA, or directive node. - -

    +

    First node or NULL if the string has errors.

    mxmlSaveAllocString

    Save an XML tree to an allocated string.

    @@ -1367,22 +1129,10 @@ char *mxmlSaveAllocString (

    node
    Node to write
    cb
    -
    Whitespace callback or MXML_NO_CALLBACK
    +
    Whitespace callback or MXML_NO_CALLBACK

    Return Value

    -

    Allocated string or NULL

    -

    Discussion

    -

    This function returns a pointer to a string containing the textual -representation of the XML node tree. The string should be freed -using the free() function when you are done with it. NULL is returned -if the node would produce an empty string or if the string cannot be -allocated.
    -
    -The callback argument specifies a function that returns a whitespace -string or NULL before and after each element. If MXML_NO_CALLBACK -is specified, whitespace will only be added before MXML_TEXT nodes -with leading whitespace and before attribute names inside opening -element tags.

    +

    Allocated string or NULL

    mxmlSaveFd

    Save an XML tree to a file descriptor.

    @@ -1398,16 +1148,10 @@ int mxmlSaveFd (

    fd
    File descriptor to write to
    cb
    -
    Whitespace callback or MXML_NO_CALLBACK
    +
    Whitespace callback or MXML_NO_CALLBACK

    Return Value

    0 on success, -1 on error.

    -

    Discussion

    -

    The callback argument specifies a function that returns a whitespace -string or NULL before and after each element. If MXML_NO_CALLBACK -is specified, whitespace will only be added before MXML_TEXT nodes -with leading whitespace and before attribute names inside opening -element tags.

    mxmlSaveFile

    Save an XML tree to a file.

    @@ -1423,16 +1167,10 @@ int mxmlSaveFile (

    fp
    File to write to
    cb
    -
    Whitespace callback or MXML_NO_CALLBACK
    +
    Whitespace callback or MXML_NO_CALLBACK

    Return Value

    0 on success, -1 on error.

    -

    Discussion

    -

    The callback argument specifies a function that returns a whitespace -string or NULL before and after each element. If MXML_NO_CALLBACK -is specified, whitespace will only be added before MXML_TEXT nodes -with leading whitespace and before attribute names inside opening -element tags.

    mxmlSaveString

    Save an XML node tree to a string.

    @@ -1451,20 +1189,10 @@ int mxmlSaveString (

    bufsize
    Size of string buffer
    cb
    -
    Whitespace callback or MXML_NO_CALLBACK
    +
    Whitespace callback or MXML_NO_CALLBACK

    Return Value

    Size of string

    -

    Discussion

    -

    This function returns the total number of bytes that would be -required for the string but only copies (bufsize - 1) characters -into the specified buffer.
    -
    -The callback argument specifies a function that returns a whitespace -string or NULL before and after each element. If MXML_NO_CALLBACK -is specified, whitespace will only be added before MXML_TEXT nodes -with leading whitespace and before attribute names inside opening -element tags.

     Mini-XML 2.3 mxmlSetCDATA

    Set the element name of a CDATA node.

    @@ -1481,10 +1209,6 @@ int mxmlSetCDATA (

    Return Value

    0 on success, -1 on failure

    -

    Discussion

    -

    The node is not changed if it (or its first child) is not a CDATA element node. - -

     Mini-XML 2.1 mxmlSetCustom

    Set the data and destructor of a custom data node.

    @@ -1504,10 +1228,6 @@ int mxmlSetCustom (

    Return Value

    0 on success, -1 on failure

    -

    Discussion

    -

    The node is not changed if it (or its first child) is not a custom node. - -

    mxmlSetCustomHandlers

    Set the handling functions for custom data.

    @@ -1522,12 +1242,6 @@ void mxmlSetCustomHandlers (

    save
    Save function
    -

    Discussion

    -

    The load function accepts a node pointer and a data string and must -return 0 on success and non-zero on error.
    -
    -The save function accepts a node pointer and must return a malloc'd -string on success and NULL on error.

    mxmlSetElement

    Set the name of an element node.

    @@ -1544,8 +1258,6 @@ int mxmlSetElement (

    Return Value

    0 on success, -1 on failure

    -

    Discussion

    -

    The node is not changed if it is not an element node.

    mxmlSetErrorCallback

    Set the error message callback.

    @@ -1573,8 +1285,6 @@ int mxmlSetInteger (

    Return Value

    0 on success, -1 on failure

    -

    Discussion

    -

    The node is not changed if it (or its first child) is not an integer node.

    mxmlSetOpaque

    Set the value of an opaque node.

    @@ -1591,8 +1301,25 @@ int mxmlSetOpaque (

    Return Value

    0 on success, -1 on failure

    -

    Discussion

    -

    The node is not changed if it (or its first child) is not an opaque node.

    +

     Mini-XML 2.11 mxmlSetOpaquef

    +

    Set the value of an opaque string node to a formatted string.

    +

    +int mxmlSetOpaquef (
    +    mxml_node_t *node,
    +    const char *format,
    +    ...
    +);

    +

    Parameters

    +
    +
    node
    +
    Node to set
    +
    format
    +
    Printf-style format string
    +
    ...
    +
    Additional arguments as needed
    +
    +

    Return Value

    +

    0 on success, -1 on failure

    mxmlSetReal

    Set the value of a real number node.

    @@ -1609,8 +1336,6 @@ int mxmlSetReal (

    Return Value

    0 on success, -1 on failure

    -

    Discussion

    -

    The node is not changed if it (or its first child) is not a real number node.

    mxmlSetText

    Set the value of a text node.

    @@ -1630,8 +1355,6 @@ int mxmlSetText (

    Return Value

    0 on success, -1 on failure

    -

    Discussion

    -

    The node is not changed if it (or its first child) is not a text node.

    mxmlSetTextf

    Set the value of a text node to a formatted string.

    @@ -1654,8 +1377,6 @@ int mxmlSetTextf (

    Return Value

    0 on success, -1 on failure

    -

    Discussion

    -

    The node is not changed if it (or its first child) is not a text node.

     Mini-XML 2.7 mxmlSetUserData

    Set the user data pointer for a node.

    @@ -1683,10 +1404,6 @@ void mxmlSetWrapMargin (

    column
    Column for wrapping, 0 to disable wrapping
    -

    Discussion

    -

    Wrapping is disabled when "column" is 0. - -

    mxmlWalkNext

    Walk to the next logical node in the tree.

    @@ -1702,14 +1419,10 @@ void mxmlSetWrapMargin (

    top
    Top node
    descend
    -
    Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST
    +
    Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST

    Return Value

    -

    Next node or NULL

    -

    Discussion

    -

    The descend argument controls whether the first child is considered -to be the next node. The top node argument constrains the walk to -the node's children.

    +

    Next node or NULL

    mxmlWalkPrev

    Walk to the previous logical node in the tree.

    @@ -1725,14 +1438,10 @@ the node's children.

    top
    Top node
    descend
    -
    Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST
    +
    Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST

    Return Value

    -

    Previous node or NULL

    -

    Discussion

    -

    The descend argument controls whether the previous node's last child -is considered to be the previous node. The top node argument constrains -the walk to the node's children.

    +

    Previous node or NULL

    Data Types

    mxml_custom_destroy_cb_t

    Custom data destructor

    diff --git a/mxml-attr.c b/mxml-attr.c index 20fe8b0..ca5531c 100644 --- a/mxml-attr.c +++ b/mxml-attr.c @@ -92,11 +92,11 @@ mxmlElementDeleteAttr(mxml_node_t *node,/* I - Element */ /* * 'mxmlElementGetAttr()' - Get an attribute. * - * This function returns NULL if the node is not an element or the + * This function returns @code NULL@ if the node is not an element or the * named attribute does not exist. */ -const char * /* O - Attribute value or NULL */ +const char * /* O - Attribute value or @code NULL@ */ mxmlElementGetAttr(mxml_node_t *node, /* I - Element node */ const char *name) /* I - Name of attribute */ { diff --git a/mxml-entity.c b/mxml-entity.c index 149b5b2..cca15b5 100644 --- a/mxml-entity.c +++ b/mxml-entity.c @@ -50,10 +50,10 @@ mxmlEntityAddCallback( /* * 'mxmlEntityGetName()' - Get the name that corresponds to the character value. * - * If val does not need to be represented by a named entity, NULL is returned. + * If val does not need to be represented by a named entity, @code NULL@ is returned. */ -const char * /* O - Entity name or NULL */ +const char * /* O - Entity name or @code NULL@ */ mxmlEntityGetName(int val) /* I - Character value */ { switch (val) diff --git a/mxml-file.c b/mxml-file.c index 39d782c..ec106a7 100644 --- a/mxml-file.c +++ b/mxml-file.c @@ -103,18 +103,15 @@ static int mxml_write_ws(mxml_node_t *node, void *p, * If no top node is provided, the XML file MUST be well-formed with a * single parent node like for the entire file. The callback * function returns the value type that should be used for child nodes. - * If MXML_NO_CALLBACK is specified then all child nodes will be either - * MXML_ELEMENT or MXML_TEXT nodes. - * - * The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK, - * MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading - * child nodes of the specified type. + * The constants @code MXML_INTEGER_CALLBACK@, @code MXML_OPAQUE_CALLBACK@, + * @code MXML_REAL_CALLBACK@, and @code MXML_TEXT_CALLBACK@ are defined for + * loading child (data) nodes of the specified type. */ -mxml_node_t * /* O - First node or NULL if the file could not be read. */ +mxml_node_t * /* O - First node or @code NULL@ if the file could not be read. */ mxmlLoadFd(mxml_node_t *top, /* I - Top node */ int fd, /* I - File descriptor to read from */ - mxml_load_cb_t cb) /* I - Callback function or MXML_NO_CALLBACK */ + mxml_load_cb_t cb) /* I - Callback function or constant */ { _mxml_fdbuf_t buf; /* File descriptor buffer */ @@ -142,18 +139,15 @@ mxmlLoadFd(mxml_node_t *top, /* I - Top node */ * If no top node is provided, the XML file MUST be well-formed with a * single parent node like for the entire file. The callback * function returns the value type that should be used for child nodes. - * If MXML_NO_CALLBACK is specified then all child nodes will be either - * MXML_ELEMENT or MXML_TEXT nodes. - * - * The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK, - * MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading - * child nodes of the specified type. + * The constants @code MXML_INTEGER_CALLBACK@, @code MXML_OPAQUE_CALLBACK@, + * @code MXML_REAL_CALLBACK@, and @code MXML_TEXT_CALLBACK@ are defined for + * loading child (data) nodes of the specified type. */ -mxml_node_t * /* O - First node or NULL if the file could not be read. */ +mxml_node_t * /* O - First node or @code NULL@ if the file could not be read. */ mxmlLoadFile(mxml_node_t *top, /* I - Top node */ FILE *fp, /* I - File to read from */ - mxml_load_cb_t cb) /* I - Callback function or MXML_NO_CALLBACK */ + mxml_load_cb_t cb) /* I - Callback function or constant */ { /* * Read the XML data... @@ -170,18 +164,15 @@ mxmlLoadFile(mxml_node_t *top, /* I - Top node */ * If no top node is provided, the XML string MUST be well-formed with a * single parent node like for the entire string. The callback * function returns the value type that should be used for child nodes. - * If MXML_NO_CALLBACK is specified then all child nodes will be either - * MXML_ELEMENT or MXML_TEXT nodes. - * - * The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK, - * MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading - * child nodes of the specified type. + * The constants @code MXML_INTEGER_CALLBACK@, @code MXML_OPAQUE_CALLBACK@, + * @code MXML_REAL_CALLBACK@, and @code MXML_TEXT_CALLBACK@ are defined for + * loading child (data) nodes of the specified type. */ -mxml_node_t * /* O - First node or NULL if the string has errors. */ +mxml_node_t * /* O - First node or @code NULL@ if the string has errors. */ mxmlLoadString(mxml_node_t *top, /* I - Top node */ const char *s, /* I - String to load */ - mxml_load_cb_t cb) /* I - Callback function or MXML_NO_CALLBACK */ + mxml_load_cb_t cb) /* I - Callback function or constant */ { /* * Read the XML data... @@ -197,21 +188,21 @@ mxmlLoadString(mxml_node_t *top, /* I - Top node */ * * This function returns a pointer to a string containing the textual * representation of the XML node tree. The string should be freed - * using the free() function when you are done with it. NULL is returned + * using the free() function when you are done with it. @code NULL@ is returned * if the node would produce an empty string or if the string cannot be * allocated. * * The callback argument specifies a function that returns a whitespace - * string or NULL before and after each element. If MXML_NO_CALLBACK - * is specified, whitespace will only be added before MXML_TEXT nodes + * string or NULL before and after each element. If @code MXML_NO_CALLBACK@ + * is specified, whitespace will only be added before @code MXML_TEXT@ nodes * with leading whitespace and before attribute names inside opening * element tags. */ -char * /* O - Allocated string or NULL */ +char * /* O - Allocated string or @code NULL@ */ mxmlSaveAllocString( mxml_node_t *node, /* I - Node to write */ - mxml_save_cb_t cb) /* I - Whitespace callback or MXML_NO_CALLBACK */ + mxml_save_cb_t cb) /* I - Whitespace callback or @code MXML_NO_CALLBACK@ */ { int bytes; /* Required bytes */ char buffer[8192]; /* Temporary buffer */ @@ -259,8 +250,8 @@ mxmlSaveAllocString( * 'mxmlSaveFd()' - Save an XML tree to a file descriptor. * * The callback argument specifies a function that returns a whitespace - * string or NULL before and after each element. If MXML_NO_CALLBACK - * is specified, whitespace will only be added before MXML_TEXT nodes + * string or NULL before and after each element. If @code MXML_NO_CALLBACK@ + * is specified, whitespace will only be added before @code MXML_TEXT@ nodes * with leading whitespace and before attribute names inside opening * element tags. */ @@ -268,7 +259,7 @@ mxmlSaveAllocString( int /* O - 0 on success, -1 on error. */ mxmlSaveFd(mxml_node_t *node, /* I - Node to write */ int fd, /* I - File descriptor to write to */ - mxml_save_cb_t cb) /* I - Whitespace callback or MXML_NO_CALLBACK */ + mxml_save_cb_t cb) /* I - Whitespace callback or @code MXML_NO_CALLBACK@ */ { int col; /* Final column */ _mxml_fdbuf_t buf; /* File descriptor buffer */ @@ -307,8 +298,8 @@ mxmlSaveFd(mxml_node_t *node, /* I - Node to write */ * 'mxmlSaveFile()' - Save an XML tree to a file. * * The callback argument specifies a function that returns a whitespace - * string or NULL before and after each element. If MXML_NO_CALLBACK - * is specified, whitespace will only be added before MXML_TEXT nodes + * string or NULL before and after each element. If @code MXML_NO_CALLBACK@ + * is specified, whitespace will only be added before @code MXML_TEXT@ nodes * with leading whitespace and before attribute names inside opening * element tags. */ @@ -316,7 +307,7 @@ mxmlSaveFd(mxml_node_t *node, /* I - Node to write */ int /* O - 0 on success, -1 on error. */ mxmlSaveFile(mxml_node_t *node, /* I - Node to write */ FILE *fp, /* I - File to write to */ - mxml_save_cb_t cb) /* I - Whitespace callback or MXML_NO_CALLBACK */ + mxml_save_cb_t cb) /* I - Whitespace callback or @code MXML_NO_CALLBACK@ */ { int col; /* Final column */ _mxml_global_t *global = _mxml_global(); @@ -350,8 +341,8 @@ mxmlSaveFile(mxml_node_t *node, /* I - Node to write */ * into the specified buffer. * * The callback argument specifies a function that returns a whitespace - * string or NULL before and after each element. If MXML_NO_CALLBACK - * is specified, whitespace will only be added before MXML_TEXT nodes + * string or NULL before and after each element. If @code MXML_NO_CALLBACK@ + * is specified, whitespace will only be added before @code MXML_TEXT@ nodes * with leading whitespace and before attribute names inside opening * element tags. */ @@ -360,7 +351,7 @@ int /* O - Size of string */ mxmlSaveString(mxml_node_t *node, /* I - Node to write */ char *buffer, /* I - String buffer */ int bufsize, /* I - Size of string buffer */ - mxml_save_cb_t cb) /* I - Whitespace callback or MXML_NO_CALLBACK */ + mxml_save_cb_t cb) /* I - Whitespace callback or @code MXML_NO_CALLBACK@ */ { int col; /* Final column */ char *ptr[2]; /* Pointers for putc_cb */ @@ -406,25 +397,22 @@ mxmlSaveString(mxml_node_t *node, /* I - Node to write */ * If no top node is provided, the XML file MUST be well-formed with a * single parent node like for the entire file. The callback * function returns the value type that should be used for child nodes. - * If MXML_NO_CALLBACK is specified then all child nodes will be either - * MXML_ELEMENT or MXML_TEXT nodes. + * The constants @code MXML_INTEGER_CALLBACK@, @code MXML_OPAQUE_CALLBACK@, + * @code MXML_REAL_CALLBACK@, and @code MXML_TEXT_CALLBACK@ are defined for + * loading child nodes of the specified type. * - * The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK, - * MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading - * child nodes of the specified type. - * - * The SAX callback must call mxmlRetain() for any nodes that need to + * The SAX callback must call @link mxmlRetain@ for any nodes that need to * be kept for later use. Otherwise, nodes are deleted when the parent * node is closed or after each data, comment, CDATA, or directive node. * * @since Mini-XML 2.3@ */ -mxml_node_t * /* O - First node or NULL if the file could not be read. */ +mxml_node_t * /* O - First node or @code NULL@ if the file could not be read. */ mxmlSAXLoadFd(mxml_node_t *top, /* I - Top node */ int fd, /* I - File descriptor to read from */ - mxml_load_cb_t cb, /* I - Callback function or MXML_NO_CALLBACK */ - mxml_sax_cb_t sax_cb, /* I - SAX callback or MXML_NO_CALLBACK */ + mxml_load_cb_t cb, /* I - Callback function or constant */ + mxml_sax_cb_t sax_cb, /* I - SAX callback or @code MXML_NO_CALLBACK@ */ void *sax_data) /* I - SAX user data */ { _mxml_fdbuf_t buf; /* File descriptor buffer */ @@ -454,26 +442,23 @@ mxmlSAXLoadFd(mxml_node_t *top, /* I - Top node */ * If no top node is provided, the XML file MUST be well-formed with a * single parent node like for the entire file. The callback * function returns the value type that should be used for child nodes. - * If MXML_NO_CALLBACK is specified then all child nodes will be either - * MXML_ELEMENT or MXML_TEXT nodes. - * - * The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK, - * MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading - * child nodes of the specified type. + * The constants @code MXML_INTEGER_CALLBACK@, @code MXML_OPAQUE_CALLBACK@, + * @code MXML_REAL_CALLBACK@, and @code MXML_TEXT_CALLBACK@ are defined for + * loading child nodes of the specified type. * - * The SAX callback must call mxmlRetain() for any nodes that need to + * The SAX callback must call @link mxmlRetain@ for any nodes that need to * be kept for later use. Otherwise, nodes are deleted when the parent * node is closed or after each data, comment, CDATA, or directive node. * * @since Mini-XML 2.3@ */ -mxml_node_t * /* O - First node or NULL if the file could not be read. */ +mxml_node_t * /* O - First node or @code NULL@ if the file could not be read. */ mxmlSAXLoadFile( mxml_node_t *top, /* I - Top node */ FILE *fp, /* I - File to read from */ - mxml_load_cb_t cb, /* I - Callback function or MXML_NO_CALLBACK */ - mxml_sax_cb_t sax_cb, /* I - SAX callback or MXML_NO_CALLBACK */ + mxml_load_cb_t cb, /* I - Callback function or constant */ + mxml_sax_cb_t sax_cb, /* I - SAX callback or @code MXML_NO_CALLBACK@ */ void *sax_data) /* I - SAX user data */ { /* @@ -492,26 +477,23 @@ mxmlSAXLoadFile( * If no top node is provided, the XML string MUST be well-formed with a * single parent node like for the entire string. The callback * function returns the value type that should be used for child nodes. - * If MXML_NO_CALLBACK is specified then all child nodes will be either - * MXML_ELEMENT or MXML_TEXT nodes. - * - * The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK, - * MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading - * child nodes of the specified type. + * The constants @code MXML_INTEGER_CALLBACK@, @code MXML_OPAQUE_CALLBACK@, + * @code MXML_REAL_CALLBACK@, and @code MXML_TEXT_CALLBACK@ are defined for + * loading child nodes of the specified type. * - * The SAX callback must call mxmlRetain() for any nodes that need to + * The SAX callback must call @link mxmlRetain@ for any nodes that need to * be kept for later use. Otherwise, nodes are deleted when the parent * node is closed or after each data, comment, CDATA, or directive node. * * @since Mini-XML 2.3@ */ -mxml_node_t * /* O - First node or NULL if the string has errors. */ +mxml_node_t * /* O - First node or @code NULL@ if the string has errors. */ mxmlSAXLoadString( mxml_node_t *top, /* I - Top node */ const char *s, /* I - String to load */ - mxml_load_cb_t cb, /* I - Callback function or MXML_NO_CALLBACK */ - mxml_sax_cb_t sax_cb, /* I - SAX callback or MXML_NO_CALLBACK */ + mxml_load_cb_t cb, /* I - Callback function or constant */ + mxml_sax_cb_t sax_cb, /* I - SAX callback or @code MXML_NO_CALLBACK@ */ void *sax_data) /* I - SAX user data */ { /* @@ -529,7 +511,7 @@ mxmlSAXLoadString( * return 0 on success and non-zero on error. * * The save function accepts a node pointer and must return a malloc'd - * string on success and NULL on error. + * string on success and @code NULL@ on error. * */ diff --git a/mxml-get.c b/mxml-get.c index 7b28c0d..abe2da5 100644 --- a/mxml-get.c +++ b/mxml-get.c @@ -28,7 +28,7 @@ * @since Mini-XML 2.7@ */ -const char * /* O - CDATA value or NULL */ +const char * /* O - CDATA value or @code NULL@ */ mxmlGetCDATA(mxml_node_t *node) /* I - Node to get */ { /* @@ -56,7 +56,7 @@ mxmlGetCDATA(mxml_node_t *node) /* I - Node to get */ * @since Mini-XML 2.7@ */ -const void * /* O - Custom value or NULL */ +const void * /* O - Custom value or @code NULL@ */ mxmlGetCustom(mxml_node_t *node) /* I - Node to get */ { /* @@ -89,7 +89,7 @@ mxmlGetCustom(mxml_node_t *node) /* I - Node to get */ * @since Mini-XML 2.7@ */ -const char * /* O - Element name or NULL */ +const char * /* O - Element name or @code NULL@ */ mxmlGetElement(mxml_node_t *node) /* I - Node to get */ { /* @@ -116,7 +116,7 @@ mxmlGetElement(mxml_node_t *node) /* I - Node to get */ * @since Mini-XML 2.7@ */ -mxml_node_t * /* O - First child or NULL */ +mxml_node_t * /* O - First child or @code NULL@ */ mxmlGetFirstChild(mxml_node_t *node) /* I - Node to get */ { /* @@ -177,7 +177,7 @@ mxmlGetInteger(mxml_node_t *node) /* I - Node to get */ * @since Mini-XML 2.7@ */ -mxml_node_t * /* O - Last child or NULL */ +mxml_node_t * /* O - Last child or @code NULL@ */ mxmlGetLastChild(mxml_node_t *node) /* I - Node to get */ { /* @@ -230,7 +230,7 @@ mxmlGetNextSibling(mxml_node_t *node) /* I - Node to get */ * @since Mini-XML 2.7@ */ -const char * /* O - Opaque string or NULL */ +const char * /* O - Opaque string or @code NULL@ */ mxmlGetOpaque(mxml_node_t *node) /* I - Node to get */ { /* @@ -263,7 +263,7 @@ mxmlGetOpaque(mxml_node_t *node) /* I - Node to get */ * @since Mini-XML 2.7@ */ -mxml_node_t * /* O - Parent node or NULL */ +mxml_node_t * /* O - Parent node or @code NULL@ */ mxmlGetParent(mxml_node_t *node) /* I - Node to get */ { /* @@ -289,7 +289,7 @@ mxmlGetParent(mxml_node_t *node) /* I - Node to get */ * @since Mini-XML 2.7@ */ -mxml_node_t * /* O - Previous node or NULL */ +mxml_node_t * /* O - Previous node or @code NULL@ */ mxmlGetPrevSibling(mxml_node_t *node) /* I - Node to get */ { /* @@ -344,12 +344,12 @@ mxmlGetReal(mxml_node_t *node) /* I - Node to get */ * 'mxmlGetText()' - Get the text value for a node or its first child. * * @code NULL@ is returned if the node (or its first child) is not a text node. - * The "whitespace" argument can be NULL. + * The "whitespace" argument can be @code NULL@. * * @since Mini-XML 2.7@ */ -const char * /* O - Text string or NULL */ +const char * /* O - Text string or @code NULL@ */ mxmlGetText(mxml_node_t *node, /* I - Node to get */ int *whitespace) /* O - 1 if string is preceded by whitespace, 0 otherwise */ { diff --git a/mxml-index.c b/mxml-index.c index 9a68618..d93768c 100644 --- a/mxml-index.c +++ b/mxml-index.c @@ -62,10 +62,12 @@ mxmlIndexDelete(mxml_index_t *ind) /* I - Index to delete */ /* * 'mxmlIndexEnum()' - Return the next node in the index. * - * Nodes are returned in the sorted order of the index. + * You should call @link mxmlIndexReset@ prior to using this function to get + * the first node in the index. Nodes are returned in the sorted order of the + * index. */ -mxml_node_t * /* O - Next node or NULL if there is none */ +mxml_node_t * /* O - Next node or @code NULL@ if there is none */ mxmlIndexEnum(mxml_index_t *ind) /* I - Index to enumerate */ { /* @@ -89,13 +91,13 @@ mxmlIndexEnum(mxml_index_t *ind) /* I - Index to enumerate */ /* * 'mxmlIndexFind()' - Find the next matching node. * - * You should call mxmlIndexReset() prior to using this function for + * You should call @link mxmlIndexReset@ prior to using this function for * the first time with a particular set of "element" and "value" - * strings. Passing NULL for both "element" and "value" is equivalent - * to calling mxmlIndexEnum(). + * strings. Passing @code NULL@ for both "element" and "value" is equivalent + * to calling @link mxmlIndexEnum@. */ -mxml_node_t * /* O - Node or NULL if none found */ +mxml_node_t * /* O - Node or @code NULL@ if none found */ mxmlIndexFind(mxml_index_t *ind, /* I - Index to search */ const char *element, /* I - Element name to find, if any */ const char *value) /* I - Attribute value, if any */ @@ -297,7 +299,7 @@ mxmlIndexGetCount(mxml_index_t *ind) /* I - Index of nodes */ * 'mxmlIndexNew()' - Create a new index. * * The index will contain all nodes that contain the named element and/or - * attribute. If both "element" and "attr" are NULL, then the index will + * attribute. If both "element" and "attr" are @code NULL@, then the index will * contain a sorted list of the elements in the node tree. Nodes are * sorted by element name and optionally by attribute value if the "attr" * argument is not NULL. @@ -305,8 +307,8 @@ mxmlIndexGetCount(mxml_index_t *ind) /* I - Index of nodes */ mxml_index_t * /* O - New index */ mxmlIndexNew(mxml_node_t *node, /* I - XML node tree */ - const char *element, /* I - Element to index or NULL for all */ - const char *attr) /* I - Attribute to index or NULL for none */ + const char *element, /* I - Element to index or @code NULL@ for all */ + const char *attr) /* I - Attribute to index or @code NULL@ for none */ { mxml_index_t *ind; /* New index */ mxml_node_t *current, /* Current node in index */ @@ -457,11 +459,11 @@ mxmlIndexNew(mxml_node_t *node, /* I - XML node tree */ * 'mxmlIndexReset()' - Reset the enumeration/find pointer in the index and * return the first node in the index. * - * This function should be called prior to using mxmlIndexEnum() or - * mxmlIndexFind() for the first time. + * This function should be called prior to using @link mxmlIndexEnum@ or + * @link mxmlIndexFind@ for the first time. */ -mxml_node_t * /* O - First node or NULL if there is none */ +mxml_node_t * /* O - First node or @code NULL@ if there is none */ mxmlIndexReset(mxml_index_t *ind) /* I - Index to reset */ { #ifdef DEBUG @@ -537,8 +539,8 @@ index_compare(mxml_index_t *ind, /* I - Index */ static int /* O - Result of comparison */ index_find(mxml_index_t *ind, /* I - Index */ - const char *element, /* I - Element name or NULL */ - const char *value, /* I - Attribute value or NULL */ + const char *element, /* I - Element name or @code NULL@ */ + const char *value, /* I - Attribute value or @code NULL@ */ mxml_node_t *node) /* I - Node */ { int diff; /* Difference */ diff --git a/mxml-node.c b/mxml-node.c index 35f957d..d2468d2 100644 --- a/mxml-node.c +++ b/mxml-node.c @@ -31,18 +31,18 @@ static mxml_node_t *mxml_new(mxml_node_t *parent, mxml_type_t type); /* * 'mxmlAdd()' - Add a node to a tree. * - * Adds the specified node to the parent. If the child argument is not - * NULL, puts the new node before or after the specified child depending - * on the value of the where argument. If the child argument is NULL, - * puts the new node at the beginning of the child list (MXML_ADD_BEFORE) - * or at the end of the child list (MXML_ADD_AFTER). The constant - * MXML_ADD_TO_PARENT can be used to specify a NULL child pointer. + * Adds the specified node to the parent. If the child argument is not + * @code NULL@, puts the new node before or after the specified child depending + * on the value of the where argument. If the child argument is @code NULL@, + * puts the new node at the beginning of the child list (@code MXML_ADD_BEFORE@) + * or at the end of the child list (@code MXML_ADD_AFTER@). The constant + * @code MXML_ADD_TO_PARENT@ can be used to specify a @code NULL@ child pointer. */ void mxmlAdd(mxml_node_t *parent, /* I - Parent node */ - int where, /* I - Where to add, MXML_ADD_BEFORE or MXML_ADD_AFTER */ - mxml_node_t *child, /* I - Child node for where or MXML_ADD_TO_PARENT */ + int where, /* I - Where to add, @code MXML_ADD_BEFORE@ or @code MXML_ADD_AFTER@ */ + mxml_node_t *child, /* I - Child node for where or @code MXML_ADD_TO_PARENT@ */ mxml_node_t *node) /* I - Node to add */ { #ifdef DEBUG @@ -170,7 +170,7 @@ mxmlAdd(mxml_node_t *parent, /* I - Parent node */ * 'mxmlDelete()' - Delete a node and all of its children. * * If the specified node has a parent, this function first removes the - * node from its parent using the mxmlRemove() function. + * node from its parent using the @link mxmlRemove@ function. */ void @@ -274,15 +274,16 @@ mxmlGetRefCount(mxml_node_t *node) /* I - Node */ * 'mxmlNewCDATA()' - Create a new CDATA node. * * The new CDATA node is added to the end of the specified parent's child - * list. The constant MXML_NO_PARENT can be used to specify that the new - * CDATA node has no parent. The data string must be nul-terminated and - * is copied into the new node. CDATA nodes use the MXML_ELEMENT type. + * list. The constant @code MXML_NO_PARENT@ can be used to specify that the new + * CDATA node has no parent. The data string must be nul-terminated and + * is copied into the new node. CDATA nodes currently use the + * @code MXML_ELEMENT@ type. * * @since Mini-XML 2.3@ */ mxml_node_t * /* O - New node */ -mxmlNewCDATA(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */ +mxmlNewCDATA(mxml_node_t *parent, /* I - Parent node or @code MXML_NO_PARENT@ */ const char *data) /* I - Data string */ { mxml_node_t *node; /* New node */ @@ -315,8 +316,8 @@ mxmlNewCDATA(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */ * 'mxmlNewCustom()' - Create a new custom data node. * * The new custom node is added to the end of the specified parent's child - * list. The constant MXML_NO_PARENT can be used to specify that the new - * element node has no parent. NULL can be passed when the data in the + * list. The constant @code MXML_NO_PARENT@ can be used to specify that the new + * element node has no parent. @code NULL@ can be passed when the data in the * node is not dynamically allocated or is separately managed. * * @since Mini-XML 2.1@ @@ -324,7 +325,7 @@ mxmlNewCDATA(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */ mxml_node_t * /* O - New node */ mxmlNewCustom( - mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */ + mxml_node_t *parent, /* I - Parent node or @code MXML_NO_PARENT@ */ void *data, /* I - Pointer to data */ mxml_custom_destroy_cb_t destroy) /* I - Function to destroy data */ { @@ -354,12 +355,12 @@ mxmlNewCustom( * 'mxmlNewElement()' - Create a new element node. * * The new element node is added to the end of the specified parent's child - * list. The constant MXML_NO_PARENT can be used to specify that the new + * list. The constant @code MXML_NO_PARENT@ can be used to specify that the new * element node has no parent. */ mxml_node_t * /* O - New node */ -mxmlNewElement(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */ +mxmlNewElement(mxml_node_t *parent, /* I - Parent node or @code MXML_NO_PARENT@ */ const char *name) /* I - Name of element */ { mxml_node_t *node; /* New node */ @@ -392,12 +393,12 @@ mxmlNewElement(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */ * 'mxmlNewInteger()' - Create a new integer node. * * The new integer node is added to the end of the specified parent's child - * list. The constant MXML_NO_PARENT can be used to specify that the new + * list. The constant @code MXML_NO_PARENT@ can be used to specify that the new * integer node has no parent. */ mxml_node_t * /* O - New node */ -mxmlNewInteger(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */ +mxmlNewInteger(mxml_node_t *parent, /* I - Parent node or @code MXML_NO_PARENT@ */ int integer) /* I - Integer value */ { mxml_node_t *node; /* New node */ @@ -421,14 +422,14 @@ mxmlNewInteger(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */ /* * 'mxmlNewOpaque()' - Create a new opaque string. * - * The new opaque node is added to the end of the specified parent's child - * list. The constant MXML_NO_PARENT can be used to specify that the new - * opaque node has no parent. The opaque string must be nul-terminated and - * is copied into the new node. + * The new opaque string node is added to the end of the specified parent's + * child list. The constant @code MXML_NO_PARENT@ can be used to specify that + * the new opaque string node has no parent. The opaque string must be nul- + * terminated and is copied into the new node. */ mxml_node_t * /* O - New node */ -mxmlNewOpaque(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */ +mxmlNewOpaque(mxml_node_t *parent, /* I - Parent node or @code MXML_NO_PARENT@ */ const char *opaque) /* I - Opaque string */ { mxml_node_t *node; /* New node */ @@ -457,16 +458,62 @@ mxmlNewOpaque(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */ } +/* + * 'mxmlNewOpaquef()' - Create a new formatted opaque string node. + * + * The new opaque string node is added to the end of the specified parent's + * child list. The constant @code MXML_NO_PARENT@ can be used to specify that + * the new opaque string node has no parent. The format string must be + * nul-terminated and is formatted into the new node. + */ + +mxml_node_t * /* O - New node */ +mxmlNewOpaquef(mxml_node_t *parent, /* I - Parent node or @code MXML_NO_PARENT@ */ + const char *format, /* I - Printf-style format string */ + ...) /* I - Additional args as needed */ +{ + mxml_node_t *node; /* New node */ + va_list ap; /* Pointer to arguments */ + + +#ifdef DEBUG + fprintf(stderr, "mxmlNewOpaquef(parent=%p, format=\"%s\", ...)\n", parent, format ? format : "(null)"); +#endif /* DEBUG */ + + /* + * Range check input... + */ + + if (!format) + return (NULL); + + /* + * Create the node and set the text value... + */ + + if ((node = mxml_new(parent, MXML_OPAQUE)) != NULL) + { + va_start(ap, format); + + node->value.opaque = _mxml_vstrdupf(format, ap); + + va_end(ap); + } + + return (node); +} + + /* * 'mxmlNewReal()' - Create a new real number node. * * The new real number node is added to the end of the specified parent's - * child list. The constant MXML_NO_PARENT can be used to specify that + * child list. The constant @code MXML_NO_PARENT@ can be used to specify that * the new real number node has no parent. */ mxml_node_t * /* O - New node */ -mxmlNewReal(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */ +mxmlNewReal(mxml_node_t *parent, /* I - Parent node or @code MXML_NO_PARENT@ */ double real) /* I - Real number value */ { mxml_node_t *node; /* New node */ @@ -491,14 +538,14 @@ mxmlNewReal(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */ * 'mxmlNewText()' - Create a new text fragment node. * * The new text node is added to the end of the specified parent's child - * list. The constant MXML_NO_PARENT can be used to specify that the new - * text node has no parent. The whitespace parameter is used to specify - * whether leading whitespace is present before the node. The text + * list. The constant @code MXML_NO_PARENT@ can be used to specify that the new + * text node has no parent. The whitespace parameter is used to specify + * whether leading whitespace is present before the node. The text * string must be nul-terminated and is copied into the new node. */ mxml_node_t * /* O - New node */ -mxmlNewText(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */ +mxmlNewText(mxml_node_t *parent, /* I - Parent node or @code MXML_NO_PARENT@ */ int whitespace, /* I - 1 = leading whitespace, 0 = no whitespace */ const char *string) /* I - String */ { @@ -535,16 +582,16 @@ mxmlNewText(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */ * 'mxmlNewTextf()' - Create a new formatted text fragment node. * * The new text node is added to the end of the specified parent's child - * list. The constant MXML_NO_PARENT can be used to specify that the new - * text node has no parent. The whitespace parameter is used to specify - * whether leading whitespace is present before the node. The format + * list. The constant @code MXML_NO_PARENT@ can be used to specify that the new + * text node has no parent. The whitespace parameter is used to specify + * whether leading whitespace is present before the node. The format * string must be nul-terminated and is formatted into the new node. */ mxml_node_t * /* O - New node */ -mxmlNewTextf(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */ +mxmlNewTextf(mxml_node_t *parent, /* I - Parent node or @code MXML_NO_PARENT@ */ int whitespace, /* I - 1 = leading whitespace, 0 = no whitespace */ - const char *format, /* I - Printf-style frmat string */ + const char *format, /* I - Printf-style format string */ ...) /* I - Additional args as needed */ { mxml_node_t *node; /* New node */ @@ -584,8 +631,8 @@ mxmlNewTextf(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */ /* * 'mxmlRemove()' - Remove a node from its parent. * - * Does not free memory used by the node - use mxmlDelete() for that. - * This function does nothing if the node has no parent. + * This function does not free memory used by the node - use @link mxmlDelete@ + * for that. This function does nothing if the node has no parent. */ void @@ -652,7 +699,7 @@ mxmlRemove(mxml_node_t *node) /* I - Node to remove */ * 'mxmlNewXML()' - Create a new XML document tree. * * The "version" argument specifies the version number to put in the - * ?xml element node. If NULL, version 1.0 is assumed. + * ?xml element node. If @code NULL@, version "1.0" is assumed. * * @since Mini-XML 2.3@ */ @@ -674,7 +721,7 @@ mxmlNewXML(const char *version) /* I - Version number to use */ * 'mxmlRelease()' - Release a node. * * When the reference count reaches zero, the node (and any children) - * is deleted via mxmlDelete(). + * is deleted via @link mxmlDelete@. * * @since Mini-XML 2.3@ */ diff --git a/mxml-search.c b/mxml-search.c index 65bb2a2..a133bff 100644 --- a/mxml-search.c +++ b/mxml-search.c @@ -24,22 +24,22 @@ * 'mxmlFindElement()' - Find the named element. * * The search is constrained by the name, attribute name, and value; any - * NULL names or values are treated as wildcards, so different kinds of + * @code NULL@ names or values are treated as wildcards, so different kinds of * searches can be implemented by looking for all elements of a given name * or all elements with a specific attribute. The descend argument determines * whether the search descends into child nodes; normally you will use - * MXML_DESCEND_FIRST for the initial search and MXML_NO_DESCEND to find - * additional direct descendents of the node. The top node argument + * @code MXML_DESCEND_FIRST@ for the initial search and @code MXML_NO_DESCEND@ + * to find additional direct descendents of the node. The top node argument * constrains the search to a particular node's children. */ -mxml_node_t * /* O - Element node or NULL */ +mxml_node_t * /* O - Element node or @code NULL@ */ mxmlFindElement(mxml_node_t *node, /* I - Current node */ mxml_node_t *top, /* I - Top node */ - const char *name, /* I - Element name or NULL for any */ - const char *attr, /* I - Attribute name, or NULL for none */ - const char *value, /* I - Attribute value, or NULL for any */ - int descend) /* I - Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST */ + const char *element, /* I - Element name or @code NULL@ for any */ + const char *attr, /* I - Attribute name, or @code NULL@ for none */ + const char *value, /* I - Attribute value, or @code NULL@ for any */ + int descend) /* I - Descend into tree - @code MXML_DESCEND@, @code MXML_NO_DESCEND@, or @code MXML_DESCEND_FIRST@ */ { const char *temp; /* Current attribute value */ @@ -69,7 +69,7 @@ mxmlFindElement(mxml_node_t *node, /* I - Current node */ if (node->type == MXML_ELEMENT && node->value.element.name && - (!name || !strcmp(node->value.element.name, name))) + (!element || !strcmp(node->value.element.name, element))) { /* * See if we need to check for an attribute... @@ -120,7 +120,7 @@ mxmlFindElement(mxml_node_t *node, /* I - Current node */ * @since Mini-XML 2.7@ */ -mxml_node_t * /* O - Found node or NULL */ +mxml_node_t * /* O - Found node or @code NULL@ */ mxmlFindPath(mxml_node_t *top, /* I - Top node */ const char *path) /* I - Path to element */ { @@ -198,14 +198,14 @@ mxmlFindPath(mxml_node_t *top, /* I - Top node */ * 'mxmlWalkNext()' - Walk to the next logical node in the tree. * * The descend argument controls whether the first child is considered - * to be the next node. The top node argument constrains the walk to + * to be the next node. The top node argument constrains the walk to * the node's children. */ -mxml_node_t * /* O - Next node or NULL */ +mxml_node_t * /* O - Next node or @code NULL@ */ mxmlWalkNext(mxml_node_t *node, /* I - Current node */ mxml_node_t *top, /* I - Top node */ - int descend) /* I - Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST */ + int descend) /* I - Descend into tree - @code MXML_DESCEND@, @code MXML_NO_DESCEND@, or @code MXML_DESCEND_FIRST@ */ { if (!node) return (NULL); @@ -236,14 +236,14 @@ mxmlWalkNext(mxml_node_t *node, /* I - Current node */ * 'mxmlWalkPrev()' - Walk to the previous logical node in the tree. * * The descend argument controls whether the previous node's last child - * is considered to be the previous node. The top node argument constrains + * is considered to be the previous node. The top node argument constrains * the walk to the node's children. */ -mxml_node_t * /* O - Previous node or NULL */ +mxml_node_t * /* O - Previous node or @code NULL@ */ mxmlWalkPrev(mxml_node_t *node, /* I - Current node */ mxml_node_t *top, /* I - Top node */ - int descend) /* I - Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST */ + int descend) /* I - Descend into tree - @code MXML_DESCEND@, @code MXML_NO_DESCEND@, or @code MXML_DESCEND_FIRST@ */ { if (!node || node == top) return (NULL); diff --git a/mxml-set.c b/mxml-set.c index b8b91a4..71ade49 100644 --- a/mxml-set.c +++ b/mxml-set.c @@ -193,6 +193,50 @@ mxmlSetOpaque(mxml_node_t *node, /* I - Node to set */ } +/* + * 'mxmlSetOpaquef()' - Set the value of an opaque string node to a formatted string. + * + * The node is not changed if it (or its first child) is not an opaque node. + * + * @since Mini-XML 2.11@ + */ + +int /* O - 0 on success, -1 on failure */ +mxmlSetOpaquef(mxml_node_t *node, /* I - Node to set */ + const char *format, /* I - Printf-style format string */ + ...) /* I - Additional arguments as needed */ +{ + va_list ap; /* Pointer to arguments */ + + + /* + * Range check input... + */ + + if (node && node->type == MXML_ELEMENT && + node->child && node->child->type == MXML_OPAQUE) + node = node->child; + + if (!node || node->type != MXML_OPAQUE || !format) + return (-1); + + /* + * Free any old string value and set the new value... + */ + + if (node->value.opaque) + free(node->value.opaque); + + va_start(ap, format); + + node->value.opaque = _mxml_strdupf(format, ap); + + va_end(ap); + + return (0); +} + + /* * 'mxmlSetReal()' - Set the value of a real number node. * diff --git a/mxml.h b/mxml.h index 7d0c0f7..5ad96b8 100644 --- a/mxml.h +++ b/mxml.h @@ -211,7 +211,7 @@ extern const char *mxmlEntityGetName(int val); extern int mxmlEntityGetValue(const char *name); extern void mxmlEntityRemoveCallback(mxml_entity_cb_t cb); extern mxml_node_t *mxmlFindElement(mxml_node_t *node, mxml_node_t *top, - const char *name, const char *attr, + const char *element, const char *attr, const char *value, int descend); extern mxml_node_t *mxmlFindPath(mxml_node_t *node, const char *path); extern const char *mxmlGetCDATA(mxml_node_t *node); @@ -250,11 +250,14 @@ extern mxml_node_t *mxmlNewCustom(mxml_node_t *parent, void *data, extern mxml_node_t *mxmlNewElement(mxml_node_t *parent, const char *name); extern mxml_node_t *mxmlNewInteger(mxml_node_t *parent, int integer); extern mxml_node_t *mxmlNewOpaque(mxml_node_t *parent, const char *opaque); +extern mxml_node_t *mxmlNewOpaquef(mxml_node_t *parent, const char *format, ...) +# ifdef __GNUC__ +__attribute__ ((__format__ (__printf__, 2, 3))) +# endif /* __GNUC__ */ +; extern mxml_node_t *mxmlNewReal(mxml_node_t *parent, double real); -extern mxml_node_t *mxmlNewText(mxml_node_t *parent, int whitespace, - const char *string); -extern mxml_node_t *mxmlNewTextf(mxml_node_t *parent, int whitespace, - const char *format, ...) +extern mxml_node_t *mxmlNewText(mxml_node_t *parent, int whitespace, const char *string); +extern mxml_node_t *mxmlNewTextf(mxml_node_t *parent, int whitespace, const char *format, ...) # ifdef __GNUC__ __attribute__ ((__format__ (__printf__, 3, 4))) # endif /* __GNUC__ */ @@ -289,6 +292,11 @@ extern int mxmlSetElement(mxml_node_t *node, const char *name); extern void mxmlSetErrorCallback(mxml_error_cb_t cb); extern int mxmlSetInteger(mxml_node_t *node, int integer); extern int mxmlSetOpaque(mxml_node_t *node, const char *opaque); +extern int mxmlSetOpaquef(mxml_node_t *node, const char *format, ...) +# ifdef __GNUC__ +__attribute__ ((__format__ (__printf__, 2, 3))) +# endif /* __GNUC__ */ +; extern int mxmlSetReal(mxml_node_t *node, double real); extern int mxmlSetText(mxml_node_t *node, int whitespace, const char *string); diff --git a/mxmldoc.c b/mxmldoc.c index 4abe707..575a534 100644 --- a/mxmldoc.c +++ b/mxmldoc.c @@ -181,7 +181,7 @@ static int scan_file(const char *filename, FILE *fp, mxml_node_t *doc); static void sort_node(mxml_node_t *tree, mxml_node_t *func); static void update_comment(mxml_node_t *parent, mxml_node_t *comment); static void usage(const char *option); -static void write_description(FILE *out, mxml_node_t *description, const char *element, int summary); +static void write_description(FILE *out, int mode, mxml_node_t *description, const char *element, int summary); #ifdef __APPLE__ static void write_docset(const char *docset, const char *section, const char *title, const char *author, const char *copyright, const char *docversion, const char *feedname, const char *feedurl, const char *cssfile, const char *headerfile, const char *bodyfile, mmd_t *body, mxml_node_t *doc, const char *footerfile); #endif /* __APPLE__ */ @@ -3632,6 +3632,7 @@ usage(const char *option) /* I - Unknown option */ static void write_description( FILE *out, /* I - Output file */ + int mode, /* I - Output mode */ mxml_node_t *description, /* I - Description node */ const char *element, /* I - HTML element, if any */ int summary) /* I - Show summary */ @@ -3775,7 +3776,10 @@ write_description( } else if (*ptr == '\n' && ptr[1] == '\n' && ptr[2] && ptr[2] != '@') { - fputs("
    \n
    \n", out); + if (mode == OUTPUT_EPUB) + fputs("
    \n
    \n", out); + else + fputs("
    \n
    \n", out); ptr ++; } else @@ -4676,7 +4680,7 @@ write_function(FILE *out, /* I - Output file */ fprintf(out, "%s%s\n", level, level == 3 ? "function" : "method", get_comment_info(description), name, name, level); if (description) - write_description(out, description, "p", 1); + write_description(out, mode, description, "p", 1); fputs("

    \n", out); @@ -4702,7 +4706,7 @@ write_function(FILE *out, /* I - Output file */ fprintf(out, "%c%s\n    ", prefix, br); if (type->child) - write_element(out, doc, type, OUTPUT_HTML); + write_element(out, doc, type, mode); fputs(mxmlElementGetAttr(arg, "name"), out); if ((defval = mxmlElementGetAttr(arg, "default")) != NULL) @@ -4729,8 +4733,8 @@ write_function(FILE *out, /* I - Output file */ adesc = mxmlFindElement(arg, arg, "description", NULL, NULL, MXML_DESCEND_FIRST); - write_description(out, adesc, "dd", 1); - write_description(out, adesc, "dd", 0); + write_description(out, mode, adesc, "dd", 1); + write_description(out, mode, adesc, "dd", 0); } fputs("\n", out); @@ -4747,15 +4751,15 @@ write_function(FILE *out, /* I - Output file */ adesc = mxmlFindElement(arg, arg, "description", NULL, NULL, MXML_DESCEND_FIRST); - write_description(out, adesc, "p", 1); - write_description(out, adesc, "p", 0); + write_description(out, mode, adesc, "p", 1); + write_description(out, mode, adesc, "p", 0); } if (description) { for (node = description->child; node; node = node->next) - if (node->value.text.string && - (sep = strstr(node->value.text.string, "\n\n")) != NULL) + if (node->value.opaque && + (sep = strstr(node->value.opaque, "\n\n")) != NULL) { sep += 2; if (*sep && strncmp(sep, "@since ", 7) && @@ -4767,7 +4771,7 @@ write_function(FILE *out, /* I - Output file */ { fprintf(out, "Discussion\n", level + 1, level + 1); - write_description(out, description, "p", 0); + write_description(out, mode, description, "p", 0); } } } @@ -5089,7 +5093,7 @@ write_html_body( fprintf(out, "

    %s%s

    \n", name, get_comment_info(description), name); if (description) - write_description(out, description, "p", 1); + write_description(out, mode, description, "p", 1); fputs("

    \n" "typedef ", out); @@ -5218,7 +5222,7 @@ write_html_body( fprintf(out, "

    %s%s

    \n", name, get_comment_info(description), name); if (description) - write_description(out, description, "p", 1); + write_description(out, mode, description, "p", 1); fputs("

    ", out); @@ -5248,7 +5252,7 @@ write_html_body( fprintf(out, "

    %s%s

    \n", name, get_comment_info(description), name); if (description) - write_description(out, description, "p", 1); + write_description(out, mode, description, "p", 1); fputs("

    Constants

    \n" "
    \n", out); @@ -5264,8 +5268,8 @@ write_html_body( fprintf(out, "
    %s %s
    \n", mxmlElementGetAttr(arg, "name"), get_comment_info(description)); - write_description(out, description, "dd", 1); - write_description(out, description, "dd", 0); + write_description(out, mode, description, "dd", 1); + write_description(out, mode, description, "dd", 0); } fputs("
    \n", out); @@ -5435,11 +5439,20 @@ write_html_head(FILE *out, /* I - Output file */ "}\n" ".variable {\n" "}\n" + "blockquote {\n" + " border: solid thin gray;\n" + " box-shadow: 3px 3px 5px rgba(0,0,0,0.5);\n" + " padding: 0px 10px;\n" + " page-break-inside: avoid;\n" + "}\n" "p code, li code, p.code, pre, ul.code li {\n" " background: rgba(127,127,127,0.1);\n" " border: thin dotted gray;\n" " font-family: monospace;\n" " font-size: 90%;\n" + " hyphens: manual;\n" + " -webkit-hyphens: manual;\n" + " page-break-inside: avoid;\n" "}\n" "p.code, pre, ul.code li {\n" " padding: 10px;\n" @@ -5681,7 +5694,7 @@ write_man(const char *man_name, /* I - Name of manpage */ NULL, MXML_DESCEND_FIRST); printf(".SS %s\n", cname); - write_description(stdout, description, NULL, 1); + write_description(stdout, OUTPUT_MAN, description, NULL, 1); printf(".PP\n" ".nf\n" @@ -5771,7 +5784,7 @@ write_man(const char *man_name, /* I - Name of manpage */ puts("};\n" ".fi"); - write_description(stdout, description, NULL, 0); + write_description(stdout, OUTPUT_MAN, description, NULL, 0); } } @@ -5792,8 +5805,8 @@ write_man(const char *man_name, /* I - Name of manpage */ NULL, MXML_DESCEND_FIRST); printf(".SS %s\n", name); - write_description(stdout, description, NULL, 1); - write_description(stdout, description, NULL, 0); + write_description(stdout, OUTPUT_MAN, description, NULL, 1); + write_description(stdout, OUTPUT_MAN, description, NULL, 0); for (arg = mxmlFindElement(scut, scut, "constant", NULL, NULL, MXML_DESCEND_FIRST); @@ -5804,7 +5817,7 @@ write_man(const char *man_name, /* I - Name of manpage */ description = mxmlFindElement(arg, arg, "description", NULL, NULL, MXML_DESCEND_FIRST); printf(".TP 5\n%s\n.br\n", mxmlElementGetAttr(arg, "name")); - write_description(stdout, description, NULL, 1); + write_description(stdout, OUTPUT_MAN, description, NULL, 1); } } } @@ -5826,7 +5839,7 @@ write_man(const char *man_name, /* I - Name of manpage */ NULL, MXML_DESCEND_FIRST); printf(".SS %s\n", name); - write_description(stdout, description, NULL, 1); + write_description(stdout, OUTPUT_MAN, description, NULL, 1); puts(".PP\n" ".nf"); @@ -5866,7 +5879,7 @@ write_man(const char *man_name, /* I - Name of manpage */ puts(".fi"); - write_description(stdout, description, NULL, 0); + write_description(stdout, OUTPUT_MAN, description, NULL, 0); } } @@ -5887,7 +5900,7 @@ write_man(const char *man_name, /* I - Name of manpage */ NULL, MXML_DESCEND_FIRST); printf(".SS %s\n", cname); - write_description(stdout, description, NULL, 1); + write_description(stdout, OUTPUT_MAN, description, NULL, 1); printf(".PP\n" ".nf\n" @@ -5956,7 +5969,7 @@ write_man(const char *man_name, /* I - Name of manpage */ puts("};\n" ".fi"); - write_description(stdout, description, NULL, 0); + write_description(stdout, OUTPUT_MAN, description, NULL, 0); } } @@ -5977,7 +5990,7 @@ write_man(const char *man_name, /* I - Name of manpage */ NULL, MXML_DESCEND_FIRST); printf(".SS %s\n", name); - write_description(stdout, description, NULL, 1); + write_description(stdout, OUTPUT_MAN, description, NULL, 1); fputs(".PP\n" ".nf\n" @@ -6020,7 +6033,7 @@ write_man(const char *man_name, /* I - Name of manpage */ puts(".fi"); - write_description(stdout, description, NULL, 0); + write_description(stdout, OUTPUT_MAN, description, NULL, 0); } } @@ -6041,7 +6054,7 @@ write_man(const char *man_name, /* I - Name of manpage */ NULL, MXML_DESCEND_FIRST); printf(".SS %s\n", name); - write_description(stdout, description, NULL, 1); + write_description(stdout, OUTPUT_MAN, description, NULL, 1); printf(".PP\n" ".nf\n" @@ -6062,7 +6075,7 @@ write_man(const char *man_name, /* I - Name of manpage */ puts("};\n" ".fi"); - write_description(stdout, description, NULL, 0); + write_description(stdout, OUTPUT_MAN, description, NULL, 0); } } @@ -6083,7 +6096,7 @@ write_man(const char *man_name, /* I - Name of manpage */ NULL, MXML_DESCEND_FIRST); printf(".SS %s\n", name); - write_description(stdout, description, NULL, 1); + write_description(stdout, OUTPUT_MAN, description, NULL, 1); puts(".PP\n" ".nf"); @@ -6097,7 +6110,7 @@ write_man(const char *man_name, /* I - Name of manpage */ puts(";\n" ".fi"); - write_description(stdout, description, NULL, 0); + write_description(stdout, OUTPUT_MAN, description, NULL, 0); } } @@ -6166,7 +6179,7 @@ write_scu(FILE *out, /* I - Output file */ fprintf(out, "

    %s%s

    \n", scut->value.element.name, get_comment_info(description), cname, cname); if (description) - write_description(out, description, "p", 1); + write_description(out, mode, description, "p", 1); fprintf(out, "

    %s %s", scut->value.element.name, cname); if ((parent = mxmlElementGetAttr(scut, "parent")) != NULL) @@ -6280,8 +6293,8 @@ write_scu(FILE *out, /* I - Output file */ fprintf(out, "

    %s %s
    \n", mxmlElementGetAttr(arg, "name"), get_comment_info(description)); - write_description(out, description, "dd", 1); - write_description(out, description, "dd", 0); + write_description(out, mode, description, "dd", 1); + write_description(out, mode, description, "dd", 0); } fputs("\n", out); @@ -6306,6 +6319,9 @@ write_string(FILE *out, /* I - Output file */ const char *s, /* I - String to write */ int mode) /* I - Output mode */ { + if (!s) + return; + switch (mode) { case OUTPUT_DOCSET : @@ -6413,7 +6429,7 @@ write_tokens(FILE *out, /* I - Output file */ " %s\n" " //apple_ref/cpp/cl/%s\n" " ", path, cename, cename); - write_description(out, description, "", 1); + write_description(out, OUTPUT_TOKENS, description, "", 1); fputs(" \n" " \n", out); @@ -6467,7 +6483,7 @@ write_tokens(FILE *out, /* I - Output file */ fputs(")\n" " ", out); - write_description(out, description, "", 1); + write_description(out, OUTPUT_TOKENS, description, "", 1); fputs(" \n" " ", out); @@ -6536,7 +6552,7 @@ write_tokens(FILE *out, /* I - Output file */ " %s\n" " //apple_ref/c/func/%s\n" " ", path, name, name); - write_description(out, description, "", 1); + write_description(out, OUTPUT_TOKENS, description, "", 1); fputs(" \n" " ", out); @@ -6602,7 +6618,7 @@ write_tokens(FILE *out, /* I - Output file */ " %s\n" " //apple_ref/c/tdef/%s\n" " ", path, name, name); - write_description(out, description, "", 1); + write_description(out, OUTPUT_TOKENS, description, "", 1); fputs(" \n" " \n", out); @@ -6627,7 +6643,7 @@ write_tokens(FILE *out, /* I - Output file */ " %s\n" " //apple_ref/c/tag/%s\n" " ", path, name, name); - write_description(out, description, "", 1); + write_description(out, OUTPUT_TOKENS, description, "", 1); fputs(" \n" " \n", out); @@ -6652,7 +6668,7 @@ write_tokens(FILE *out, /* I - Output file */ " %s\n" " //apple_ref/c/tag/%s\n" " ", path, name, name); - write_description(out, description, "", 1); + write_description(out, OUTPUT_TOKENS, description, "", 1); fputs(" \n" " \n", out); @@ -6677,7 +6693,7 @@ write_tokens(FILE *out, /* I - Output file */ " %s\n" " //apple_ref/c/data/%s\n" " ", path, name, name); - write_description(out, description, "", 1); + write_description(out, OUTPUT_TOKENS, description, "", 1); fputs(" \n" " \n", out); @@ -6702,7 +6718,7 @@ write_tokens(FILE *out, /* I - Output file */ " %s\n" " //apple_ref/c/tag/%s\n" " ", path, cename, cename); - write_description(out, description, "", 1); + write_description(out, OUTPUT_TOKENS, description, "", 1); fputs(" \n" " \n", out); @@ -6720,7 +6736,7 @@ write_tokens(FILE *out, /* I - Output file */ " %s\n" " //apple_ref/c/econst/%s\n" " ", path, cename, name); - write_description(out, description, "", 1); + write_description(out, OUTPUT_TOKENS, description, "", 1); fputs(" \n" " \n", out); }