mirror of
https://github.com/michaelrsweet/mxml.git
synced 2024-11-08 13:39:58 +00:00
Rebuild doco files, update web site.
This commit is contained in:
parent
725aaec2d8
commit
8ace1524af
@ -848,11 +848,53 @@ mxmlSetInteger()</TT></A>, <A href="#mxmlSetOpaque"><TT>mxmlSetOpaque()</TT>
|
||||
<P>Once the index is created, the <A href="#mxmlIndexEnum"><TT>
|
||||
mxmlIndexEnum()</TT></A>, <A href="#mxmlIndexFind"><TT>mxmlIndexFind()</TT>
|
||||
</A>, and <A href="#mxmlIndexReset"><TT>mxmlIndexReset()</TT></A>
|
||||
functions are used to access the nodes in the index. The <A href="#mxmlIndexEnum">
|
||||
<TT>mxmlIndexEnum()</TT></A> function enumerates each of the nodes in
|
||||
the index.</P>
|
||||
<P>The <A href="#mxmlIndexFind"><TT>mxmlIndexFind()</TT></A> function</P>
|
||||
<P>The <A href="#mxmlIndexReset"><TT>mxmlIndexReset()</TT></A> function</P>
|
||||
functions are used to access the nodes in the index. The <A href="#mxmlIndexReset">
|
||||
<TT>mxmlIndexReset()</TT></A> function resets the "current" node pointer
|
||||
in the index, allowing you to do new searches and enumerations on the
|
||||
same index. Typically you will call this function prior to your calls
|
||||
to <A href="#mxmlIndexEnum"><TT>mxmlIndexEnum()</TT></A> and <A href="#mxmlIndexFind">
|
||||
<TT>mxmlIndexFind()</TT></A>.</P>
|
||||
<P>The <A href="#mxmlIndexEnum"><TT>mxmlIndexEnum()</TT></A> function
|
||||
enumerates each of the nodes in the index and can be used in a loop as
|
||||
follows:</P>
|
||||
<PRE>
|
||||
<A href="#mxml_node_t">mxml_node_t</A> *node;
|
||||
<A href="#mxml_index_t">mxml_index_t</A> *ind;
|
||||
|
||||
mxmlIndexReset(ind);
|
||||
|
||||
while ((node = mxmlIndexEnum(ind)) != NULL)
|
||||
{
|
||||
// do something with node
|
||||
}
|
||||
</PRE>
|
||||
<P>The <A href="#mxmlIndexFind"><TT>mxmlIndexFind()</TT></A> function
|
||||
locates the next occurrence of the named element and attribute value in
|
||||
the index. It can be used to find all matching elements in an index, as
|
||||
follows:</P>
|
||||
<PRE>
|
||||
<A href="#mxml_node_t">mxml_node_t</A> *node;
|
||||
<A href="#mxml_index_t">mxml_index_t</A> *ind;
|
||||
|
||||
mxmlIndexReset(ind);
|
||||
|
||||
while ((node = mxmlIndexFind(ind, "element", "attr-value")) != NULL)
|
||||
{
|
||||
// do something with node
|
||||
}
|
||||
</PRE>
|
||||
<P>The second and third arguments represent the element name and
|
||||
attribute value, respectively. A <TT>NULL</TT> pointer is used to
|
||||
return all elements or attributes in the index. Passing <TT>NULL</TT>
|
||||
for both the element name and attribute value is equivalent to calling <TT>
|
||||
mxmlIndexEnum</TT>.</P>
|
||||
<P>When you are done using the index, delete it using the <A href="#mxmlIndexDelete()">
|
||||
<TT>mxmlIndexDelete()</TT></A> function:</P>
|
||||
<PRE>
|
||||
<A href="#mxml_index_t">mxml_index_t</A> *ind;
|
||||
|
||||
mxmlIndexDelete(ind);
|
||||
</PRE>
|
||||
<HR NOSHADE>
|
||||
<H1 align="right"><A name="MXMLDOC">4 - Using the mxmldoc Utility</A></H1>
|
||||
<P>This chapter describes how to use the <TT>mxmldoc(1)</TT> utility
|
||||
@ -1590,6 +1632,7 @@ mxmldoc</TT> to generate correct documentation for the code. Single line
|
||||
<H2><A NAME="7_1">Changes in Mini-XML 2.0</A></H2>
|
||||
<UL>
|
||||
<LI>New programmers manual.</LI>
|
||||
<LI>Added Visual C++ project files for Microsoft Windows users.</LI>
|
||||
<LI>Added optimizations to mxmldoc, mxmlSaveFile(), and mxmlIndexNew()
|
||||
(STR #2)</LI>
|
||||
<LI>mxmlEntityAddCallback() now returns an integer status (STR #2)</LI>
|
||||
|
@ -30,6 +30,10 @@ PRE { font-family: monospace }
|
||||
<H2><A NAME="7_1">Changes in Mini-XML 2.0</A></H2>
|
||||
<UL>
|
||||
<LI>New programmers manual.</LI>
|
||||
<LI>Added Visual C++ project files for Microsoft Windows users.</LI>
|
||||
<LI>Added optimizations to mxmldoc, mxmlSaveFile(), and mxmlIndexNew()
|
||||
(STR #2)</LI>
|
||||
<LI>mxmlEntityAddCallback() now returns an integer status (STR #2)</LI>
|
||||
<LI>Added UTF-16 support (input only; all output is UTF-8)</LI>
|
||||
<LI>Added index functions to build a searchable index of XML nodes.</LI>
|
||||
<LI>Added character entity callback interface to support additional
|
||||
|
@ -28,6 +28,23 @@ PRE { font-family: monospace }
|
||||
<A HREF="FormattedText.html">Next</A>
|
||||
<HR NOSHADE>
|
||||
<H2><A NAME="4_3">Changing Node Values</A></H2>
|
||||
<P>All of the examples so far have concentrated on creating and loading
|
||||
new XML data nodes. Many applications, however, need to manipulate or
|
||||
change the nodes during their operation, so Mini-XML provides functions
|
||||
to change node values safely and without leaking memory.</P>
|
||||
<P>Existing nodes can be changed using the <A href="mxmlSetElement.html#mxmlSetElement">
|
||||
<TT>mxmlSetElement()</TT></A>, <A href="mxmlSetInteger.html#mxmlSetInteger">
|
||||
<TT>mxmlSetInteger()</TT></A>, <A href="mxmlSetOpaque.html#mxmlSetOpaque">
|
||||
<TT>mxmlSetOpaque()</TT></A>, <A href="mxmlSetReal.html#mxmlSetReal"><TT>
|
||||
mxmlSetReal()</TT></A>, and <A href="mxmlSetText.html#mxmlSetText"><TT>
|
||||
mxmlSetText()</TT></A> functions. For example, use the following
|
||||
function call to change a text node to contain the text "new" with
|
||||
leading whitespace:</P>
|
||||
<PRE>
|
||||
<A href="mxmlnodet.html#mxml_node_t">mxml_node_t</A> *node;
|
||||
|
||||
<A href="mxmlSetText.html#mxmlSetText">mxmlSetText</A>(node, 1, "new");
|
||||
</PRE>
|
||||
<HR NOSHADE>
|
||||
<A HREF="toc.html">Contents</A>
|
||||
<A HREF="SaveCallbacks.html">Previous</A>
|
||||
|
@ -7,7 +7,7 @@
|
||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=iso-iso-8859-1">
|
||||
<LINK REL="Start" HREF="index.html">
|
||||
<LINK REL="Contents" HREF="toc.html">
|
||||
<LINK REL="Prev" HREF="LoadingandSavingXMLFiles.html">
|
||||
<LINK REL="Prev" HREF="SavingXML.html">
|
||||
<LINK REL="Next" HREF="3MoreMiniXMLProgrammingTechniques.html">
|
||||
<STYLE TYPE="text/css"><!--
|
||||
BODY { font-family: serif }
|
||||
@ -24,10 +24,10 @@ PRE { font-family: monospace }
|
||||
</HEAD>
|
||||
<BODY>
|
||||
<A HREF="toc.html">Contents</A>
|
||||
<A HREF="LoadingandSavingXMLFiles.html">Previous</A>
|
||||
<A HREF="SavingXML.html">Previous</A>
|
||||
<A HREF="3MoreMiniXMLProgrammingTechniques.html">Next</A>
|
||||
<HR NOSHADE>
|
||||
<H3><A NAME="3_3_1">Finding and Iterating Nodes</A></H3>
|
||||
<H3><A NAME="3_4_1">Finding and Iterating Nodes</A></H3>
|
||||
<P>The <A href="mxmlWalkPrev.html#mxmlWalkPrev"><TT>mxmlWalkPrev()</TT></A>
|
||||
and <A href="mxmlWalkNext.html#mxmlWalkNext"><TT>mxmlWalkNext()</TT></A>
|
||||
functions can be used to iterate through the XML node tree:</P>
|
||||
@ -121,7 +121,7 @@ functions can be used to iterate through the XML node tree:</P>
|
||||
</UL>
|
||||
<HR NOSHADE>
|
||||
<A HREF="toc.html">Contents</A>
|
||||
<A HREF="LoadingandSavingXMLFiles.html">Previous</A>
|
||||
<A HREF="SavingXML.html">Previous</A>
|
||||
<A HREF="3MoreMiniXMLProgrammingTechniques.html">Next</A>
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
@ -28,6 +28,17 @@ PRE { font-family: monospace }
|
||||
<A HREF="Indexing.html">Next</A>
|
||||
<HR NOSHADE>
|
||||
<H2><A NAME="4_4">Formatted Text</A></H2>
|
||||
<P>The <A href="mxmlNewTextf.html#mxmlNewTextf"><TT>mxmlNewTextf()</TT></A>
|
||||
and <A href="mxmlSetTextf.html#mxmlSetTextf"><TT>mxmlSetTextf()</TT></A>
|
||||
functions create and change text nodes, respectively, using <TT>printf</TT>
|
||||
-style format strings and arguments. For example, use the following
|
||||
function call to create a new text node:</P>
|
||||
<PRE>
|
||||
<A href="mxmlnodet.html#mxml_node_t">mxml_node_t</A> *node;
|
||||
|
||||
node = <A href="mxmlNewTextf.html#mxmlNewTextf">mxmlNewTextf</A>(node, 1, "%s/%s",
|
||||
path, filename);
|
||||
</PRE>
|
||||
<HR NOSHADE>
|
||||
<A HREF="toc.html">Contents</A>
|
||||
<A HREF="ChangingNodeValues.html">Previous</A>
|
||||
|
@ -44,8 +44,8 @@ libxml2</TT> library with something substantially smaller and
|
||||
libxml2.</P>
|
||||
<P>Thanks to lots of feedback and support from various developers,
|
||||
Mini-XML has evolved since then to provide a more complete XML
|
||||
implementation and now stands at a whopping 2,240 lines of code,
|
||||
compared to 96,335 lines of code for libxml2 version 2.6.9. Aside from
|
||||
implementation and now stands at a whopping 2,713 lines of code,
|
||||
compared to 103,893 lines of code for libxml2 version 2.6.9. Aside from
|
||||
Gimp-Print, Mini-XML is used for the following projects/software
|
||||
applications:</P>
|
||||
<UL>
|
||||
|
@ -28,6 +28,81 @@ PRE { font-family: monospace }
|
||||
<A HREF="4UsingthemxmldocUtility.html">Next</A>
|
||||
<HR NOSHADE>
|
||||
<H2><A NAME="4_5">Indexing</A></H2>
|
||||
<P>Mini-XML provides functions for managing indices of nodes. The
|
||||
current implementation provides the same functionality as the <A href="mxmlFindElement.html#mxmlFindElement">
|
||||
<TT>mxmlFindElement()</TT></A>. The advantage of using an index is that
|
||||
searching and enumeration of elements is significantly faster. The only
|
||||
disadvantage is that each index is a static snapshot of the XML
|
||||
document, so indices are not well suited to XML data that is updated
|
||||
more often than it is searched. The overhead of creating an index is
|
||||
approximately equal to walking the XML document tree. Nodes in the
|
||||
index are sorted by element name and attribute value.</P>
|
||||
<P>Indices are stored in <A href="mxmlindext.html#mxml_index_t"><TT>
|
||||
mxml_index_t</TT></A> structures. The <A href="mxmlIndexNew.html#mxmlIndexNew">
|
||||
<TT>mxmlIndexNew()</TT></A> function creates a new index:</P>
|
||||
<PRE>
|
||||
<A href="mxmlnodet.html#mxml_node_t">mxml_node_t</A> *tree;
|
||||
<A href="mxmlindext.html#mxml_index_t">mxml_index_t</A> *ind;
|
||||
|
||||
ind = <A href="mxmlIndexNew.html#mxmlIndexNew">mxmlIndexNew</A>(tree, "element", "attribute");
|
||||
</PRE>
|
||||
<P>The first argument is the XML node tree to index. Normally this will
|
||||
be a pointer to the <TT>?xml</TT> element.</P>
|
||||
<P>The second argument contains the element to index; passing <TT>NULL</TT>
|
||||
indexes all element nodes alphabetically.</P>
|
||||
<P>The third argument contains the attribute to index; passing <TT>NULL</TT>
|
||||
causes only the element name to be indexed.</P>
|
||||
<P>Once the index is created, the <A href="mxmlIndexEnum.html#mxmlIndexEnum">
|
||||
<TT>mxmlIndexEnum()</TT></A>, <A href="mxmlIndexFind.html#mxmlIndexFind">
|
||||
<TT>mxmlIndexFind()</TT></A>, and <A href="mxmlIndexReset.html#mxmlIndexReset">
|
||||
<TT>mxmlIndexReset()</TT></A> functions are used to access the nodes in
|
||||
the index. The <A href="mxmlIndexReset.html#mxmlIndexReset"><TT>
|
||||
mxmlIndexReset()</TT></A> function resets the "current" node pointer in
|
||||
the index, allowing you to do new searches and enumerations on the same
|
||||
index. Typically you will call this function prior to your calls to <A href="mxmlIndexEnum.html#mxmlIndexEnum">
|
||||
<TT>mxmlIndexEnum()</TT></A> and <A href="mxmlIndexFind.html#mxmlIndexFind">
|
||||
<TT>mxmlIndexFind()</TT></A>.</P>
|
||||
<P>The <A href="mxmlIndexEnum.html#mxmlIndexEnum"><TT>mxmlIndexEnum()</TT>
|
||||
</A> function enumerates each of the nodes in the index and can be used
|
||||
in a loop as follows:</P>
|
||||
<PRE>
|
||||
<A href="mxmlnodet.html#mxml_node_t">mxml_node_t</A> *node;
|
||||
<A href="mxmlindext.html#mxml_index_t">mxml_index_t</A> *ind;
|
||||
|
||||
mxmlIndexReset(ind);
|
||||
|
||||
while ((node = mxmlIndexEnum(ind)) != NULL)
|
||||
{
|
||||
// do something with node
|
||||
}
|
||||
</PRE>
|
||||
<P>The <A href="mxmlIndexFind.html#mxmlIndexFind"><TT>mxmlIndexFind()</TT>
|
||||
</A> function locates the next occurrence of the named element and
|
||||
attribute value in the index. It can be used to find all matching
|
||||
elements in an index, as follows:</P>
|
||||
<PRE>
|
||||
<A href="mxmlnodet.html#mxml_node_t">mxml_node_t</A> *node;
|
||||
<A href="mxmlindext.html#mxml_index_t">mxml_index_t</A> *ind;
|
||||
|
||||
mxmlIndexReset(ind);
|
||||
|
||||
while ((node = mxmlIndexFind(ind, "element", "attr-value")) != NULL)
|
||||
{
|
||||
// do something with node
|
||||
}
|
||||
</PRE>
|
||||
<P>The second and third arguments represent the element name and
|
||||
attribute value, respectively. A <TT>NULL</TT> pointer is used to
|
||||
return all elements or attributes in the index. Passing <TT>NULL</TT>
|
||||
for both the element name and attribute value is equivalent to calling <TT>
|
||||
mxmlIndexEnum</TT>.</P>
|
||||
<P>When you are done using the index, delete it using the <A href="#mxmlIndexDelete()">
|
||||
<TT>mxmlIndexDelete()</TT></A> function:</P>
|
||||
<PRE>
|
||||
<A href="mxmlindext.html#mxml_index_t">mxml_index_t</A> *ind;
|
||||
|
||||
mxmlIndexDelete(ind);
|
||||
</PRE>
|
||||
<HR NOSHADE>
|
||||
<A HREF="toc.html">Contents</A>
|
||||
<A HREF="FormattedText.html">Previous</A>
|
||||
|
@ -27,7 +27,74 @@ PRE { font-family: monospace }
|
||||
<A HREF="3MoreMiniXMLProgrammingTechniques.html">Previous</A>
|
||||
<A HREF="SaveCallbacks.html">Next</A>
|
||||
<HR NOSHADE>
|
||||
<H2><A NAME="4_1">Load Callbacks</A></H2>
|
||||
<H2><A name="LOAD_CALLBACKS">Load Callbacks</A></H2>
|
||||
<P><A href="#LOAD_XML">Chapter 2</A> introduced the <A href="mxmlLoadFile.html#mxmlLoadFile">
|
||||
<TT>mxmlLoadFile()</TT></A> and <A href="mxmlLoadString.html#mxmlLoadString">
|
||||
<TT>mxmlLoadString()</TT></A> functions. The last argument to these
|
||||
functions is a callback function which is used to determine the value
|
||||
type of each data node in an XML document.</P>
|
||||
<P>Mini-XML defines several standard callbacks for simple XML data
|
||||
files:</P>
|
||||
<UL>
|
||||
<LI><TT>MXML_INTEGER_CALLBACK</TT> - All data nodes contain
|
||||
whitespace-separated integers.</LI>
|
||||
<LI><TT>MXML_OPAQUE_CALLBACK</TT> - All data nodes contain opaque
|
||||
strings ("CDATA").</LI>
|
||||
<LI><TT>MXML_REAL_CALLBACK</TT> - All data nodes contain
|
||||
whitespace-separated floating-point numbers.</LI>
|
||||
<LI><TT>MXML_TEXT_CALLBACK</TT> - All data nodes contain
|
||||
whitespace-separated strings.</LI>
|
||||
</UL>
|
||||
<P>You can provide your own callback functions for more complex XML
|
||||
documents. Your callback function will receive a pointer to the current
|
||||
element node and must return the value type of the immediate children
|
||||
for that element node: <TT>MXML_INTEGER</TT>, <TT>MXML_OPAQUE</TT>, <TT>
|
||||
MXML_REAL</TT>, or <TT>MXML_TEXT</TT>. The function is called<I> after</I>
|
||||
the element and its attributes have been read, so you can look at the
|
||||
element name, attributes, and attribute values to determine the proper
|
||||
value type to return.</P>
|
||||
|
||||
<!-- NEED 2in -->
|
||||
<P>The following callback function looks for an attribute named "type"
|
||||
or the element name to determine the value type for its child nodes:</P>
|
||||
<PRE>
|
||||
/*
|
||||
* 'type_cb()' - XML data type callback for mxmlLoadFile()...
|
||||
*/
|
||||
|
||||
mxml_type_t /* O - Data type */
|
||||
type_cb(mxml_node_t *node) /* I - Element node */
|
||||
{
|
||||
const char *type; /* Type string */
|
||||
|
||||
|
||||
/*
|
||||
* You can lookup attributes and/or use the element name, hierarchy, etc...
|
||||
*/
|
||||
|
||||
if ((type = mxmlElementGetAttr(node, "type")) == NULL)
|
||||
type = node->value.element.name;
|
||||
|
||||
if (!strcmp(type, "integer"))
|
||||
return (MXML_INTEGER);
|
||||
else if (!strcmp(type, "opaque"))
|
||||
return (MXML_OPAQUE);
|
||||
else if (!strcmp(type, "real"))
|
||||
return (MXML_REAL);
|
||||
else
|
||||
return (MXML_TEXT);
|
||||
}
|
||||
</PRE>
|
||||
<P>To use this callback function, simply use the name when you call any
|
||||
of the load functions:</P>
|
||||
<PRE>
|
||||
FILE *fp;
|
||||
<A href="mxmlnodet.html#mxml_node_t">mxml_node_t</A> *tree;
|
||||
|
||||
fp = fopen("filename.xml", "r");
|
||||
tree = <A href="mxmlLoadFile.html#mxmlLoadFile">mxmlLoadFile</A>(NULL, fp, <B>type_cb</B>);
|
||||
fclose(fp);
|
||||
</PRE>
|
||||
<HR NOSHADE>
|
||||
<A HREF="toc.html">Contents</A>
|
||||
<A HREF="3MoreMiniXMLProgrammingTechniques.html">Previous</A>
|
||||
|
74
www/docfiles/LoadingXML.html
Normal file
74
www/docfiles/LoadingXML.html
Normal file
@ -0,0 +1,74 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>Mini-XML Programmers Manual, Version 2.0</TITLE>
|
||||
<META NAME="author" CONTENT="Michael Sweet">
|
||||
<META NAME="copyright" CONTENT="Copyright 2003-2004">
|
||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=iso-iso-8859-1">
|
||||
<LINK REL="Start" HREF="index.html">
|
||||
<LINK REL="Contents" HREF="toc.html">
|
||||
<LINK REL="Prev" HREF="Nodes.html">
|
||||
<LINK REL="Next" HREF="SavingXML.html">
|
||||
<STYLE TYPE="text/css"><!--
|
||||
BODY { font-family: serif }
|
||||
H1 { font-family: sans-serif }
|
||||
H2 { font-family: sans-serif }
|
||||
H3 { font-family: sans-serif }
|
||||
H4 { font-family: sans-serif }
|
||||
H5 { font-family: sans-serif }
|
||||
H6 { font-family: sans-serif }
|
||||
SUB { font-size: smaller }
|
||||
SUP { font-size: smaller }
|
||||
PRE { font-family: monospace }
|
||||
--></STYLE>
|
||||
</HEAD>
|
||||
<BODY>
|
||||
<A HREF="toc.html">Contents</A>
|
||||
<A HREF="Nodes.html">Previous</A>
|
||||
<A HREF="SavingXML.html">Next</A>
|
||||
<HR NOSHADE>
|
||||
<H2><A NAME="3_3">Loading XML</A></H2>
|
||||
<P>You load an XML file using the <A href="mxmlLoadFile.html#mxmlLoadFile">
|
||||
<TT>mxmlLoadFile()</TT></A> function:</P>
|
||||
<PRE>
|
||||
FILE *fp;
|
||||
<A href="mxmlnodet.html#mxml_node_t">mxml_node_t</A> *tree;
|
||||
|
||||
fp = fopen("filename.xml", "r");
|
||||
tree = <A href="mxmlLoadFile.html#mxmlLoadFile">mxmlLoadFile</A>(NULL, fp, MXML_NO_CALLBACK);
|
||||
fclose(fp);
|
||||
</PRE>
|
||||
<P>The first argument specifies an existing XML parent node, if any.
|
||||
Normally you will pass <TT>NULL</TT> for this argument unless you are
|
||||
combining multiple XML sources. The XML file must contain a complete
|
||||
XML document including the <TT>?xml</TT> element if the parent node is <TT>
|
||||
NULL</TT>.</P>
|
||||
<P>The second argument specifies the stdio file to read from, as opened
|
||||
by <TT>fopen()</TT> or <TT>popen()</TT>. You can also use <TT>stdin</TT>
|
||||
if you are implementing an XML filter program.</P>
|
||||
<P>The third argument specifies a callback function which returns the
|
||||
value type of the immediate children for a new element node: <TT>
|
||||
MXML_INTEGER</TT>, <TT>MXML_OPAQUE</TT>, <TT>MXML_REAL</TT>, or <TT>
|
||||
MXML_TEXT</TT>. Load callbacks are described in detail in <A href="LoadCallbacks.html#LOAD_CALLBACKS">
|
||||
Chapter 3</A>. The example code uses the <TT>MXML_NO_CALLBACK</TT>
|
||||
constant which specifies that all data nodes in the document contain
|
||||
whitespace-separated text values.</P>
|
||||
<P>The <A href="mxmlLoadString.html#mxmlLoadString"><TT>mxmlLoadString()</TT>
|
||||
</A> function loads XML node trees from a string:</P>
|
||||
<PRE>
|
||||
char buffer[8192];
|
||||
<A href="mxmlnodet.html#mxml_node_t">mxml_node_t</A> *tree;
|
||||
|
||||
...
|
||||
tree = <A href="mxmlLoadString.html#mxmlLoadString">mxmlLoadString</A>(NULL, buffer, MXML_NO_CALLBACK);
|
||||
</PRE>
|
||||
<P>The first and third arguments are the same as used for <TT>
|
||||
mxmlLoadFile()</TT>. The second argument specifies the string or
|
||||
character buffer to load and must be a complete XML document including
|
||||
the <TT>?xml</TT> element if the parent node is <TT>NULL</TT>.</P>
|
||||
<HR NOSHADE>
|
||||
<A HREF="toc.html">Contents</A>
|
||||
<A HREF="Nodes.html">Previous</A>
|
||||
<A HREF="SavingXML.html">Next</A>
|
||||
</BODY>
|
||||
</HTML>
|
@ -8,7 +8,7 @@
|
||||
<LINK REL="Start" HREF="index.html">
|
||||
<LINK REL="Contents" HREF="toc.html">
|
||||
<LINK REL="Prev" HREF="TheBasics.html">
|
||||
<LINK REL="Next" HREF="LoadingandSavingXMLFiles.html">
|
||||
<LINK REL="Next" HREF="LoadingXML.html">
|
||||
<STYLE TYPE="text/css"><!--
|
||||
BODY { font-family: serif }
|
||||
H1 { font-family: sans-serif }
|
||||
@ -25,7 +25,7 @@ PRE { font-family: monospace }
|
||||
<BODY>
|
||||
<A HREF="toc.html">Contents</A>
|
||||
<A HREF="TheBasics.html">Previous</A>
|
||||
<A HREF="LoadingandSavingXMLFiles.html">Next</A>
|
||||
<A HREF="LoadingXML.html">Next</A>
|
||||
<HR NOSHADE>
|
||||
<H2><A NAME="3_2">Nodes</A></H2>
|
||||
<P>Every piece of information in an XML file (elements, text, numbers)
|
||||
@ -86,6 +86,6 @@ child</TT>), to the left (<TT>prev</TT>), and to the right (<TT>next</TT>
|
||||
<HR NOSHADE>
|
||||
<A HREF="toc.html">Contents</A>
|
||||
<A HREF="TheBasics.html">Previous</A>
|
||||
<A HREF="LoadingandSavingXMLFiles.html">Next</A>
|
||||
<A HREF="LoadingXML.html">Next</A>
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
@ -27,7 +27,94 @@ PRE { font-family: monospace }
|
||||
<A HREF="LoadCallbacks.html">Previous</A>
|
||||
<A HREF="ChangingNodeValues.html">Next</A>
|
||||
<HR NOSHADE>
|
||||
<H2><A NAME="4_2">Save Callbacks</A></H2>
|
||||
<H2><A name="SAVE_CALLBACKS">Save Callbacks</A></H2>
|
||||
<P><A href="#LOAD_XML">Chapter 2</A> also introduced the <A href="mxmlSaveFile.html#mxmlSaveFile">
|
||||
<TT>mxmlSaveFile()</TT></A>, <A href="mxmlSaveString.html#mxmlSaveString">
|
||||
<TT>mxmlSaveString()</TT></A>, and <A href="mxmlSaveAllocString.html#mxmlSaveAllocString">
|
||||
<TT>mxmlSaveAllocString()</TT></A> functions. The last argument to these
|
||||
functions is a callback function which is used to automatically insert
|
||||
whitespace in an XML document.</P>
|
||||
<P>Your callback function will be called up to four times for each
|
||||
element node with a pointer to the node and a "where" value of <TT>
|
||||
MXML_WS_BEFORE_OPEN</TT>, <TT>MXML_WS_AFTER_OPEN</TT>, <TT>
|
||||
MXML_WS_BEFORE_CLOSE</TT>, or <TT>MXML_WS_AFTER_CLOSE</TT>. The callback
|
||||
function should return <TT>NULL</TT> if no whitespace should be added
|
||||
and the string to insert (spaces, tabs, carriage returns, and newlines)
|
||||
otherwise. The following whitespace callback can be used to add
|
||||
whitespace to XHTML output to make it more readable in a standard text
|
||||
editor:</P>
|
||||
|
||||
<!-- NEW PAGE -->
|
||||
<PRE>
|
||||
/*
|
||||
* 'whitespace_cb()' - Let the mxmlSaveFile() function know when to insert
|
||||
* newlines and tabs...
|
||||
*/
|
||||
|
||||
const char * /* O - Whitespace string or NULL */
|
||||
whitespace_cb(mxml_node_t *node, /* I - Element node */
|
||||
int where) /* I - Open or close tag? */
|
||||
{
|
||||
const char *name; /* Name of element */
|
||||
|
||||
/*
|
||||
* We can conditionally break to a new line before or after any element.
|
||||
* These are just common HTML elements...
|
||||
*/
|
||||
|
||||
name = node->value.element.name;
|
||||
|
||||
if (!strcmp(name, "html") || !strcmp(name, "head") || !strcmp(name, "body") ||
|
||||
!strcmp(name, "pre") || !strcmp(name, "p") ||
|
||||
!strcmp(name, "h1") || !strcmp(name, "h2") || !strcmp(name, "h3") ||
|
||||
!strcmp(name, "h4") || !strcmp(name, "h5") || !strcmp(name, "h6"))
|
||||
{
|
||||
/*
|
||||
* Newlines before open and after close...
|
||||
*/
|
||||
|
||||
if (where == MXML_WS_BEFORE_OPEN || where == MXML_WS_AFTER_CLOSE)
|
||||
return ("\n");
|
||||
}
|
||||
else if (!strcmp(name, "dl") || !strcmp(name, "ol") || !strcmp(name, "ul"))
|
||||
{
|
||||
/*
|
||||
* Put a newline before and after list elements...
|
||||
*/
|
||||
|
||||
return ("\n");
|
||||
}
|
||||
else if (!strcmp(name, "dd") || !strcmp(name, "dt") || !strcmp(name, "li"))
|
||||
{
|
||||
/*
|
||||
* Put a tab before <li>'s, <dd>'s, and <dt>'s, and a newline after them...
|
||||
*/
|
||||
|
||||
if (where == MXML_WS_BEFORE_OPEN)
|
||||
return ("\t");
|
||||
else if (where == MXML_WS_AFTER_CLOSE)
|
||||
return ("\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Return NULL for no added whitespace...
|
||||
*/
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
</PRE>
|
||||
|
||||
<!-- NEW PAGE -->
|
||||
<P>To use this callback function, simply use the name when you call any
|
||||
of the save functions:</P>
|
||||
<PRE>
|
||||
FILE *fp;
|
||||
<A href="mxmlnodet.html#mxml_node_t">mxml_node_t</A> *tree;
|
||||
|
||||
fp = fopen("filename.xml", "w");
|
||||
<A href="mxmlSaveFile.html#mxmlSaveFile">mxmlSaveFile</A>(tree, fp, whitespace_cb);
|
||||
fclose(fp);
|
||||
</PRE>
|
||||
<HR NOSHADE>
|
||||
<A HREF="toc.html">Contents</A>
|
||||
<A HREF="LoadCallbacks.html">Previous</A>
|
||||
|
74
www/docfiles/SavingXML.html
Normal file
74
www/docfiles/SavingXML.html
Normal file
@ -0,0 +1,74 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>Mini-XML Programmers Manual, Version 2.0</TITLE>
|
||||
<META NAME="author" CONTENT="Michael Sweet">
|
||||
<META NAME="copyright" CONTENT="Copyright 2003-2004">
|
||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=iso-iso-8859-1">
|
||||
<LINK REL="Start" HREF="index.html">
|
||||
<LINK REL="Contents" HREF="toc.html">
|
||||
<LINK REL="Prev" HREF="LoadingXML.html">
|
||||
<LINK REL="Next" HREF="FindingandIteratingNodes.html">
|
||||
<STYLE TYPE="text/css"><!--
|
||||
BODY { font-family: serif }
|
||||
H1 { font-family: sans-serif }
|
||||
H2 { font-family: sans-serif }
|
||||
H3 { font-family: sans-serif }
|
||||
H4 { font-family: sans-serif }
|
||||
H5 { font-family: sans-serif }
|
||||
H6 { font-family: sans-serif }
|
||||
SUB { font-size: smaller }
|
||||
SUP { font-size: smaller }
|
||||
PRE { font-family: monospace }
|
||||
--></STYLE>
|
||||
</HEAD>
|
||||
<BODY>
|
||||
<A HREF="toc.html">Contents</A>
|
||||
<A HREF="LoadingXML.html">Previous</A>
|
||||
<A HREF="FindingandIteratingNodes.html">Next</A>
|
||||
<HR NOSHADE>
|
||||
<H2><A NAME="3_4">Saving XML</A></H2>
|
||||
<P>You save an XML file using the <A href="mxmlSaveFile.html#mxmlSaveFile">
|
||||
<TT>mxmlSaveFile()</TT></A> function:</P>
|
||||
<PRE>
|
||||
FILE *fp;
|
||||
<A href="mxmlnodet.html#mxml_node_t">mxml_node_t</A> *tree;
|
||||
|
||||
fp = fopen("filename.xml", "w");
|
||||
<A href="mxmlSaveFile.html#mxmlSaveFile">mxmlSaveFile</A>(tree, fp, MXML_NO_CALLBACK);
|
||||
fclose(fp);
|
||||
</PRE>
|
||||
<P>The first argument is the XML node tree to save. It should normally
|
||||
be a pointer to the top-level <TT>?xml</TT> node in your XML document.</P>
|
||||
<P>The second argument is the stdio file to write to, as opened by <TT>
|
||||
fopen()</TT> or <TT>popen()</TT>. You can also use <TT>stdout</TT> if
|
||||
you are implementing an XML filter program.</P>
|
||||
<P>The third argument is the whitespace callback to use when saving the
|
||||
file. Whitespace callbacks are covered in detail in <A href="SAVE_CALLBACKS">
|
||||
Chapter 3</A>. The example code above uses the <TT>MXML_NO_CALLBACK</TT>
|
||||
constant to specify that no special whitespace handling is required.</P>
|
||||
<P>The <A href="mxmlSaveAllocString.html#mxmlSaveAllocString"><TT>
|
||||
mxmlSaveAllocString()</TT></A>, and <A href="mxmlSaveString.html#mxmlSaveString">
|
||||
<TT>mxmlSaveString()</TT></A> functions save XML node trees to strings:</P>
|
||||
<PRE>
|
||||
char buffer[8192];
|
||||
char *ptr;
|
||||
<A href="mxmlnodet.html#mxml_node_t">mxml_node_t</A> *tree;
|
||||
|
||||
...
|
||||
<A href="mxmlSaveString.html#mxmlSaveString">mxmlSaveString</A>(tree, buffer, sizeof(buffer), MXML_NO_CALLBACK);
|
||||
|
||||
...
|
||||
ptr = <A href="mxmlSaveAllocString.html#mxmlSaveAllocString">mxmlSaveAllocString</A>(tree, MXML_NO_CALLBACK);
|
||||
</PRE>
|
||||
<P>The first and last arguments are the same as used for <TT>
|
||||
mxmlSaveFile()</TT>. The <TT>mxmlSaveString()</TT> function takes
|
||||
pointer and size arguments for saving the XML document to a fixed-size
|
||||
buffer, while <TT>mxmlSaveAllocString()</TT> returns a string buffer
|
||||
that was allocated using <TT>malloc()</TT>.</P>
|
||||
<HR NOSHADE>
|
||||
<A HREF="toc.html">Contents</A>
|
||||
<A HREF="LoadingXML.html">Previous</A>
|
||||
<A HREF="FindingandIteratingNodes.html">Next</A>
|
||||
</BODY>
|
||||
</HTML>
|
@ -33,7 +33,7 @@ PRE { font-family: monospace }
|
||||
<P>Add a callback to convert entities to Unicode.</P>
|
||||
<H4>Syntax</H4>
|
||||
<PRE>
|
||||
void
|
||||
int
|
||||
mxmlEntityAddCallback(
|
||||
int (*cb)(const char *name));
|
||||
</PRE>
|
||||
@ -47,7 +47,7 @@ mxmlEntityAddCallback(
|
||||
add</TD></TR>
|
||||
</TABLE>
|
||||
<H4>Returns</H4>
|
||||
<P>Nothing.</P>
|
||||
<P>0 on success, -1 on failure</P>
|
||||
|
||||
<!-- NEW PAGE -->
|
||||
<HR NOSHADE>
|
||||
|
@ -46,18 +46,18 @@ PRE { font-family: monospace }
|
||||
<UL>
|
||||
<LI><A HREF="TheBasics.html#3_1">The Basics</A></LI>
|
||||
<LI><A HREF="Nodes.html#3_2">Nodes</A></LI>
|
||||
<LI><A HREF="LoadingandSavingXMLFiles.html#3_3">Loading and Saving XML
|
||||
Files</A></LI>
|
||||
<LI><A HREF="LoadingXML.html#3_3">Loading XML</A></LI>
|
||||
<LI><A HREF="SavingXML.html#3_4">Saving XML</A></LI>
|
||||
<UL>
|
||||
<LI><A HREF="FindingandIteratingNodes.html#3_3_1">Finding and Iterating
|
||||
<LI><A HREF="FindingandIteratingNodes.html#3_4_1">Finding and Iterating
|
||||
Nodes</A></LI>
|
||||
</UL>
|
||||
</UL>
|
||||
<B><A HREF="3MoreMiniXMLProgrammingTechniques.html#ADVANCED">3 - More
|
||||
Mini-XML Programming Techniques</A></B>
|
||||
<UL>
|
||||
<LI><A HREF="LoadCallbacks.html#4_1">Load Callbacks</A></LI>
|
||||
<LI><A HREF="SaveCallbacks.html#4_2">Save Callbacks</A></LI>
|
||||
<LI><A HREF="LoadCallbacks.html#LOAD_CALLBACKS">Load Callbacks</A></LI>
|
||||
<LI><A HREF="SaveCallbacks.html#SAVE_CALLBACKS">Save Callbacks</A></LI>
|
||||
<LI><A HREF="ChangingNodeValues.html#4_3">Changing Node Values</A></LI>
|
||||
<LI><A HREF="FormattedText.html#4_4">Formatted Text</A></LI>
|
||||
<LI><A HREF="Indexing.html#4_5">Indexing</A></LI>
|
||||
|
347
www/mxml.html
347
www/mxml.html
@ -47,15 +47,16 @@ Copyright 2003-2004<BR>
|
||||
<UL>
|
||||
<LI><A HREF="#3_1">The Basics</A></LI>
|
||||
<LI><A HREF="#3_2">Nodes</A></LI>
|
||||
<LI><A HREF="#3_3">Loading and Saving XML Files</A></LI>
|
||||
<LI><A HREF="#3_3">Loading XML</A></LI>
|
||||
<LI><A HREF="#3_4">Saving XML</A></LI>
|
||||
<UL>
|
||||
<LI><A HREF="#3_3_1">Finding and Iterating Nodes</A></LI>
|
||||
<LI><A HREF="#3_4_1">Finding and Iterating Nodes</A></LI>
|
||||
</UL>
|
||||
</UL>
|
||||
<B><A HREF="#ADVANCED">3 - More Mini-XML Programming Techniques</A></B>
|
||||
<UL>
|
||||
<LI><A HREF="#4_1">Load Callbacks</A></LI>
|
||||
<LI><A HREF="#4_2">Save Callbacks</A></LI>
|
||||
<LI><A HREF="#LOAD_CALLBACKS">Load Callbacks</A></LI>
|
||||
<LI><A HREF="#SAVE_CALLBACKS">Save Callbacks</A></LI>
|
||||
<LI><A HREF="#4_3">Changing Node Values</A></LI>
|
||||
<LI><A HREF="#4_4">Formatted Text</A></LI>
|
||||
<LI><A HREF="#4_5">Indexing</A></LI>
|
||||
@ -217,8 +218,8 @@ libxml2</TT> library with something substantially smaller and
|
||||
libxml2.</P>
|
||||
<P>Thanks to lots of feedback and support from various developers,
|
||||
Mini-XML has evolved since then to provide a more complete XML
|
||||
implementation and now stands at a whopping 2,240 lines of code,
|
||||
compared to 96,335 lines of code for libxml2 version 2.6.9. Aside from
|
||||
implementation and now stands at a whopping 2,713 lines of code,
|
||||
compared to 103,893 lines of code for libxml2 version 2.6.9. Aside from
|
||||
Gimp-Print, Mini-XML is used for the following projects/software
|
||||
applications:</P>
|
||||
<UL>
|
||||
@ -460,7 +461,7 @@ mxmlDelete()</TT></A> function to recursively free the memory that is
|
||||
<PRE>
|
||||
mxmlDelete(tree);
|
||||
</PRE>
|
||||
<H2><A NAME="3_3">Loading and Saving XML Files</A></H2>
|
||||
<H2><A NAME="3_3">Loading XML</A></H2>
|
||||
<P>You load an XML file using the <A href="#mxmlLoadFile"><TT>
|
||||
mxmlLoadFile()</TT></A> function:</P>
|
||||
<PRE>
|
||||
@ -471,14 +472,36 @@ mxmlLoadFile()</TT></A> function:</P>
|
||||
tree = <A href="#mxmlLoadFile">mxmlLoadFile</A>(NULL, fp, MXML_NO_CALLBACK);
|
||||
fclose(fp);
|
||||
</PRE>
|
||||
<P>The first argument specifies an existing XML parent node, if any.
|
||||
Normally you will pass <TT>NULL</TT> for this argument unless you are
|
||||
combining multiple XML sources. The XML file must contain a complete
|
||||
XML document including the <TT>?xml</TT> element if the parent node is <TT>
|
||||
NULL</TT>.</P>
|
||||
<P>The second argument specifies the stdio file to read from, as opened
|
||||
by <TT>fopen()</TT> or <TT>popen()</TT>. You can also use <TT>stdin</TT>
|
||||
if you are implementing an XML filter program.</P>
|
||||
<P>The third argument specifies a callback function which returns the
|
||||
value type of the immediate children for a new element node: <TT>
|
||||
MXML_INTEGER</TT>, <TT>MXML_OPAQUE</TT>, <TT>MXML_REAL</TT>, or <TT>
|
||||
MXML_TEXT</TT>. This function is called<I> after</I> the element and its
|
||||
attributes have been read, so you can look at the element name,
|
||||
attributes, and attribute values to determine the proper value type to
|
||||
return. The default value type is MXML_TEXT if no callback is used.</P>
|
||||
<P>Similarly, you save an XML file using the <A href="#mxmlSaveFile"><TT>
|
||||
MXML_TEXT</TT>. Load callbacks are described in detail in <A href="#LOAD_CALLBACKS">
|
||||
Chapter 3</A>. The example code uses the <TT>MXML_NO_CALLBACK</TT>
|
||||
constant which specifies that all data nodes in the document contain
|
||||
whitespace-separated text values.</P>
|
||||
<P>The <A href="#mxmlLoadString"><TT>mxmlLoadString()</TT></A> function
|
||||
loads XML node trees from a string:</P>
|
||||
<PRE>
|
||||
char buffer[8192];
|
||||
<A href="#mxml_node_t">mxml_node_t</A> *tree;
|
||||
|
||||
...
|
||||
tree = <A href="#mxmlLoadString">mxmlLoadString</A>(NULL, buffer, MXML_NO_CALLBACK);
|
||||
</PRE>
|
||||
<P>The first and third arguments are the same as used for <TT>
|
||||
mxmlLoadFile()</TT>. The second argument specifies the string or
|
||||
character buffer to load and must be a complete XML document including
|
||||
the <TT>?xml</TT> element if the parent node is <TT>NULL</TT>.</P>
|
||||
<H2><A NAME="3_4">Saving XML</A></H2>
|
||||
<P>You save an XML file using the <A href="#mxmlSaveFile"><TT>
|
||||
mxmlSaveFile()</TT></A> function:</P>
|
||||
<PRE>
|
||||
FILE *fp;
|
||||
@ -488,33 +511,35 @@ mxmlSaveFile()</TT></A> function:</P>
|
||||
<A href="#mxmlSaveFile">mxmlSaveFile</A>(tree, fp, MXML_NO_CALLBACK);
|
||||
fclose(fp);
|
||||
</PRE>
|
||||
<P>Callback functions for saving are used to optionally insert
|
||||
whitespace before and after elements in the node tree. Your function
|
||||
will be called up to four times for each element node with a pointer to
|
||||
the node and a "where" value of <TT>MXML_WS_BEFORE_OPEN</TT>, <TT>
|
||||
MXML_WS_AFTER_OPEN</TT>, <TT>MXML_WS_BEFORE_CLOSE</TT>, or <TT>
|
||||
MXML_WS_AFTER_CLOSE</TT>. The callback function should return <TT>NULL</TT>
|
||||
if no whitespace should be added and the string to insert (spaces,
|
||||
tabs, carriage returns, and newlines) otherwise.</P>
|
||||
<P>The <A href="#mxmlLoadString"><TT>mxmlLoadString()</TT></A>, <A href="#mxmlSaveAllocString">
|
||||
<TT>mxmlSaveAllocString()</TT></A>, and <A href="#mxmlSaveString"><TT>
|
||||
mxmlSaveString()</TT></A> functions load XML node trees from and save
|
||||
XML node trees to strings:</P>
|
||||
<P>The first argument is the XML node tree to save. It should normally
|
||||
be a pointer to the top-level <TT>?xml</TT> node in your XML document.</P>
|
||||
<P>The second argument is the stdio file to write to, as opened by <TT>
|
||||
fopen()</TT> or <TT>popen()</TT>. You can also use <TT>stdout</TT> if
|
||||
you are implementing an XML filter program.</P>
|
||||
<P>The third argument is the whitespace callback to use when saving the
|
||||
file. Whitespace callbacks are covered in detail in <A href="SAVE_CALLBACKS">
|
||||
Chapter 3</A>. The example code above uses the <TT>MXML_NO_CALLBACK</TT>
|
||||
constant to specify that no special whitespace handling is required.</P>
|
||||
<P>The <A href="#mxmlSaveAllocString"><TT>mxmlSaveAllocString()</TT></A>
|
||||
, and <A href="#mxmlSaveString"><TT>mxmlSaveString()</TT></A> functions
|
||||
save XML node trees to strings:</P>
|
||||
<PRE>
|
||||
char buffer[8192];
|
||||
char *ptr;
|
||||
<A href="#mxml_node_t">mxml_node_t</A> *tree;
|
||||
|
||||
...
|
||||
tree = <A href="#mxmlLoadString">mxmlLoadString</A>(NULL, buffer, MXML_NO_CALLBACK);
|
||||
|
||||
...
|
||||
<A href="#mxmlSaveString">mxmlSaveString</A>(tree, buffer, sizeof(buffer), MXML_NO_CALLBACK);
|
||||
|
||||
...
|
||||
ptr = <A href="#mxmlSaveAllocString">mxmlSaveAllocString</A>(tree, MXML_NO_CALLBACK);
|
||||
</PRE>
|
||||
<H3><A NAME="3_3_1">Finding and Iterating Nodes</A></H3>
|
||||
<P>The first and last arguments are the same as used for <TT>
|
||||
mxmlSaveFile()</TT>. The <TT>mxmlSaveString()</TT> function takes
|
||||
pointer and size arguments for saving the XML document to a fixed-size
|
||||
buffer, while <TT>mxmlSaveAllocString()</TT> returns a string buffer
|
||||
that was allocated using <TT>malloc()</TT>.</P>
|
||||
<H3><A NAME="3_4_1">Finding and Iterating Nodes</A></H3>
|
||||
<P>The <A href="#mxmlWalkPrev"><TT>mxmlWalkPrev()</TT></A> and <A href="#mxmlWalkNext">
|
||||
<TT>mxmlWalkNext()</TT></A>functions can be used to iterate through the
|
||||
XML node tree:</P>
|
||||
@ -611,11 +636,265 @@ mxmlSaveString()</TT></A> functions load XML node trees from and save
|
||||
Techniques</A></H1>
|
||||
<P>This chapter shows additional ways to use the Mini-XML library in
|
||||
your programs.</P>
|
||||
<H2><A NAME="4_1">Load Callbacks</A></H2>
|
||||
<H2><A NAME="4_2">Save Callbacks</A></H2>
|
||||
<H2><A name="LOAD_CALLBACKS">Load Callbacks</A></H2>
|
||||
<P><A href="#LOAD_XML">Chapter 2</A> introduced the <A href="#mxmlLoadFile">
|
||||
<TT>mxmlLoadFile()</TT></A> and <A href="#mxmlLoadString"><TT>
|
||||
mxmlLoadString()</TT></A> functions. The last argument to these
|
||||
functions is a callback function which is used to determine the value
|
||||
type of each data node in an XML document.</P>
|
||||
<P>Mini-XML defines several standard callbacks for simple XML data
|
||||
files:</P>
|
||||
<UL>
|
||||
<LI><TT>MXML_INTEGER_CALLBACK</TT> - All data nodes contain
|
||||
whitespace-separated integers.</LI>
|
||||
<LI><TT>MXML_OPAQUE_CALLBACK</TT> - All data nodes contain opaque
|
||||
strings ("CDATA").</LI>
|
||||
<LI><TT>MXML_REAL_CALLBACK</TT> - All data nodes contain
|
||||
whitespace-separated floating-point numbers.</LI>
|
||||
<LI><TT>MXML_TEXT_CALLBACK</TT> - All data nodes contain
|
||||
whitespace-separated strings.</LI>
|
||||
</UL>
|
||||
<P>You can provide your own callback functions for more complex XML
|
||||
documents. Your callback function will receive a pointer to the current
|
||||
element node and must return the value type of the immediate children
|
||||
for that element node: <TT>MXML_INTEGER</TT>, <TT>MXML_OPAQUE</TT>, <TT>
|
||||
MXML_REAL</TT>, or <TT>MXML_TEXT</TT>. The function is called<I> after</I>
|
||||
the element and its attributes have been read, so you can look at the
|
||||
element name, attributes, and attribute values to determine the proper
|
||||
value type to return.</P>
|
||||
|
||||
<!-- NEED 2in -->
|
||||
<P>The following callback function looks for an attribute named "type"
|
||||
or the element name to determine the value type for its child nodes:</P>
|
||||
<PRE>
|
||||
/*
|
||||
* 'type_cb()' - XML data type callback for mxmlLoadFile()...
|
||||
*/
|
||||
|
||||
mxml_type_t /* O - Data type */
|
||||
type_cb(mxml_node_t *node) /* I - Element node */
|
||||
{
|
||||
const char *type; /* Type string */
|
||||
|
||||
|
||||
/*
|
||||
* You can lookup attributes and/or use the element name, hierarchy, etc...
|
||||
*/
|
||||
|
||||
if ((type = mxmlElementGetAttr(node, "type")) == NULL)
|
||||
type = node->value.element.name;
|
||||
|
||||
if (!strcmp(type, "integer"))
|
||||
return (MXML_INTEGER);
|
||||
else if (!strcmp(type, "opaque"))
|
||||
return (MXML_OPAQUE);
|
||||
else if (!strcmp(type, "real"))
|
||||
return (MXML_REAL);
|
||||
else
|
||||
return (MXML_TEXT);
|
||||
}
|
||||
</PRE>
|
||||
<P>To use this callback function, simply use the name when you call any
|
||||
of the load functions:</P>
|
||||
<PRE>
|
||||
FILE *fp;
|
||||
<A href="#mxml_node_t">mxml_node_t</A> *tree;
|
||||
|
||||
fp = fopen("filename.xml", "r");
|
||||
tree = <A href="#mxmlLoadFile">mxmlLoadFile</A>(NULL, fp, <B>type_cb</B>);
|
||||
fclose(fp);
|
||||
</PRE>
|
||||
<H2><A name="SAVE_CALLBACKS">Save Callbacks</A></H2>
|
||||
<P><A href="#LOAD_XML">Chapter 2</A> also introduced the <A href="#mxmlSaveFile">
|
||||
<TT>mxmlSaveFile()</TT></A>, <A href="#mxmlSaveString"><TT>
|
||||
mxmlSaveString()</TT></A>, and <A href="#mxmlSaveAllocString"><TT>
|
||||
mxmlSaveAllocString()</TT></A> functions. The last argument to these
|
||||
functions is a callback function which is used to automatically insert
|
||||
whitespace in an XML document.</P>
|
||||
<P>Your callback function will be called up to four times for each
|
||||
element node with a pointer to the node and a "where" value of <TT>
|
||||
MXML_WS_BEFORE_OPEN</TT>, <TT>MXML_WS_AFTER_OPEN</TT>, <TT>
|
||||
MXML_WS_BEFORE_CLOSE</TT>, or <TT>MXML_WS_AFTER_CLOSE</TT>. The callback
|
||||
function should return <TT>NULL</TT> if no whitespace should be added
|
||||
and the string to insert (spaces, tabs, carriage returns, and newlines)
|
||||
otherwise. The following whitespace callback can be used to add
|
||||
whitespace to XHTML output to make it more readable in a standard text
|
||||
editor:</P>
|
||||
|
||||
<!-- NEW PAGE -->
|
||||
<PRE>
|
||||
/*
|
||||
* 'whitespace_cb()' - Let the mxmlSaveFile() function know when to insert
|
||||
* newlines and tabs...
|
||||
*/
|
||||
|
||||
const char * /* O - Whitespace string or NULL */
|
||||
whitespace_cb(mxml_node_t *node, /* I - Element node */
|
||||
int where) /* I - Open or close tag? */
|
||||
{
|
||||
const char *name; /* Name of element */
|
||||
|
||||
/*
|
||||
* We can conditionally break to a new line before or after any element.
|
||||
* These are just common HTML elements...
|
||||
*/
|
||||
|
||||
name = node->value.element.name;
|
||||
|
||||
if (!strcmp(name, "html") || !strcmp(name, "head") || !strcmp(name, "body") ||
|
||||
!strcmp(name, "pre") || !strcmp(name, "p") ||
|
||||
!strcmp(name, "h1") || !strcmp(name, "h2") || !strcmp(name, "h3") ||
|
||||
!strcmp(name, "h4") || !strcmp(name, "h5") || !strcmp(name, "h6"))
|
||||
{
|
||||
/*
|
||||
* Newlines before open and after close...
|
||||
*/
|
||||
|
||||
if (where == MXML_WS_BEFORE_OPEN || where == MXML_WS_AFTER_CLOSE)
|
||||
return ("\n");
|
||||
}
|
||||
else if (!strcmp(name, "dl") || !strcmp(name, "ol") || !strcmp(name, "ul"))
|
||||
{
|
||||
/*
|
||||
* Put a newline before and after list elements...
|
||||
*/
|
||||
|
||||
return ("\n");
|
||||
}
|
||||
else if (!strcmp(name, "dd") || !strcmp(name, "dt") || !strcmp(name, "li"))
|
||||
{
|
||||
/*
|
||||
* Put a tab before <li>'s, <dd>'s, and <dt>'s, and a newline after them...
|
||||
*/
|
||||
|
||||
if (where == MXML_WS_BEFORE_OPEN)
|
||||
return ("\t");
|
||||
else if (where == MXML_WS_AFTER_CLOSE)
|
||||
return ("\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Return NULL for no added whitespace...
|
||||
*/
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
</PRE>
|
||||
|
||||
<!-- NEW PAGE -->
|
||||
<P>To use this callback function, simply use the name when you call any
|
||||
of the save functions:</P>
|
||||
<PRE>
|
||||
FILE *fp;
|
||||
<A href="#mxml_node_t">mxml_node_t</A> *tree;
|
||||
|
||||
fp = fopen("filename.xml", "w");
|
||||
<A href="#mxmlSaveFile">mxmlSaveFile</A>(tree, fp, whitespace_cb);
|
||||
fclose(fp);
|
||||
</PRE>
|
||||
<H2><A NAME="4_3">Changing Node Values</A></H2>
|
||||
<P>All of the examples so far have concentrated on creating and loading
|
||||
new XML data nodes. Many applications, however, need to manipulate or
|
||||
change the nodes during their operation, so Mini-XML provides functions
|
||||
to change node values safely and without leaking memory.</P>
|
||||
<P>Existing nodes can be changed using the <A href="#mxmlSetElement"><TT>
|
||||
mxmlSetElement()</TT></A>, <A href="#mxmlSetInteger"><TT>
|
||||
mxmlSetInteger()</TT></A>, <A href="#mxmlSetOpaque"><TT>mxmlSetOpaque()</TT>
|
||||
</A>, <A href="#mxmlSetReal"><TT>mxmlSetReal()</TT></A>, and <A href="#mxmlSetText">
|
||||
<TT>mxmlSetText()</TT></A> functions. For example, use the following
|
||||
function call to change a text node to contain the text "new" with
|
||||
leading whitespace:</P>
|
||||
<PRE>
|
||||
<A href="#mxml_node_t">mxml_node_t</A> *node;
|
||||
|
||||
<A href="#mxmlSetText">mxmlSetText</A>(node, 1, "new");
|
||||
</PRE>
|
||||
<H2><A NAME="4_4">Formatted Text</A></H2>
|
||||
<P>The <A href="#mxmlNewTextf"><TT>mxmlNewTextf()</TT></A> and <A href="#mxmlSetTextf">
|
||||
<TT>mxmlSetTextf()</TT></A> functions create and change text nodes,
|
||||
respectively, using <TT>printf</TT>-style format strings and arguments.
|
||||
For example, use the following function call to create a new text node:</P>
|
||||
<PRE>
|
||||
<A href="#mxml_node_t">mxml_node_t</A> *node;
|
||||
|
||||
node = <A href="#mxmlNewTextf">mxmlNewTextf</A>(node, 1, "%s/%s",
|
||||
path, filename);
|
||||
</PRE>
|
||||
<H2><A NAME="4_5">Indexing</A></H2>
|
||||
<P>Mini-XML provides functions for managing indices of nodes. The
|
||||
current implementation provides the same functionality as the <A href="#mxmlFindElement">
|
||||
<TT>mxmlFindElement()</TT></A>. The advantage of using an index is that
|
||||
searching and enumeration of elements is significantly faster. The only
|
||||
disadvantage is that each index is a static snapshot of the XML
|
||||
document, so indices are not well suited to XML data that is updated
|
||||
more often than it is searched. The overhead of creating an index is
|
||||
approximately equal to walking the XML document tree. Nodes in the
|
||||
index are sorted by element name and attribute value.</P>
|
||||
<P>Indices are stored in <A href="#mxml_index_t"><TT>mxml_index_t</TT></A>
|
||||
structures. The <A href="#mxmlIndexNew"><TT>mxmlIndexNew()</TT></A>
|
||||
function creates a new index:</P>
|
||||
<PRE>
|
||||
<A href="#mxml_node_t">mxml_node_t</A> *tree;
|
||||
<A href="#mxml_index_t">mxml_index_t</A> *ind;
|
||||
|
||||
ind = <A href="#mxmlIndexNew">mxmlIndexNew</A>(tree, "element", "attribute");
|
||||
</PRE>
|
||||
<P>The first argument is the XML node tree to index. Normally this will
|
||||
be a pointer to the <TT>?xml</TT> element.</P>
|
||||
<P>The second argument contains the element to index; passing <TT>NULL</TT>
|
||||
indexes all element nodes alphabetically.</P>
|
||||
<P>The third argument contains the attribute to index; passing <TT>NULL</TT>
|
||||
causes only the element name to be indexed.</P>
|
||||
<P>Once the index is created, the <A href="#mxmlIndexEnum"><TT>
|
||||
mxmlIndexEnum()</TT></A>, <A href="#mxmlIndexFind"><TT>mxmlIndexFind()</TT>
|
||||
</A>, and <A href="#mxmlIndexReset"><TT>mxmlIndexReset()</TT></A>
|
||||
functions are used to access the nodes in the index. The <A href="#mxmlIndexReset">
|
||||
<TT>mxmlIndexReset()</TT></A> function resets the "current" node pointer
|
||||
in the index, allowing you to do new searches and enumerations on the
|
||||
same index. Typically you will call this function prior to your calls
|
||||
to <A href="#mxmlIndexEnum"><TT>mxmlIndexEnum()</TT></A> and <A href="#mxmlIndexFind">
|
||||
<TT>mxmlIndexFind()</TT></A>.</P>
|
||||
<P>The <A href="#mxmlIndexEnum"><TT>mxmlIndexEnum()</TT></A> function
|
||||
enumerates each of the nodes in the index and can be used in a loop as
|
||||
follows:</P>
|
||||
<PRE>
|
||||
<A href="#mxml_node_t">mxml_node_t</A> *node;
|
||||
<A href="#mxml_index_t">mxml_index_t</A> *ind;
|
||||
|
||||
mxmlIndexReset(ind);
|
||||
|
||||
while ((node = mxmlIndexEnum(ind)) != NULL)
|
||||
{
|
||||
// do something with node
|
||||
}
|
||||
</PRE>
|
||||
<P>The <A href="#mxmlIndexFind"><TT>mxmlIndexFind()</TT></A> function
|
||||
locates the next occurrence of the named element and attribute value in
|
||||
the index. It can be used to find all matching elements in an index, as
|
||||
follows:</P>
|
||||
<PRE>
|
||||
<A href="#mxml_node_t">mxml_node_t</A> *node;
|
||||
<A href="#mxml_index_t">mxml_index_t</A> *ind;
|
||||
|
||||
mxmlIndexReset(ind);
|
||||
|
||||
while ((node = mxmlIndexFind(ind, "element", "attr-value")) != NULL)
|
||||
{
|
||||
// do something with node
|
||||
}
|
||||
</PRE>
|
||||
<P>The second and third arguments represent the element name and
|
||||
attribute value, respectively. A <TT>NULL</TT> pointer is used to
|
||||
return all elements or attributes in the index. Passing <TT>NULL</TT>
|
||||
for both the element name and attribute value is equivalent to calling <TT>
|
||||
mxmlIndexEnum</TT>.</P>
|
||||
<P>When you are done using the index, delete it using the <A href="#mxmlIndexDelete()">
|
||||
<TT>mxmlIndexDelete()</TT></A> function:</P>
|
||||
<PRE>
|
||||
<A href="#mxml_index_t">mxml_index_t</A> *ind;
|
||||
|
||||
mxmlIndexDelete(ind);
|
||||
</PRE>
|
||||
<HR NOSHADE>
|
||||
<H1 align="right"><A name="MXMLDOC">4 - Using the mxmldoc Utility</A></H1>
|
||||
<P>This chapter describes how to use the <TT>mxmldoc(1)</TT> utility
|
||||
@ -1353,6 +1632,10 @@ mxmldoc</TT> to generate correct documentation for the code. Single line
|
||||
<H2><A NAME="7_1">Changes in Mini-XML 2.0</A></H2>
|
||||
<UL>
|
||||
<LI>New programmers manual.</LI>
|
||||
<LI>Added Visual C++ project files for Microsoft Windows users.</LI>
|
||||
<LI>Added optimizations to mxmldoc, mxmlSaveFile(), and mxmlIndexNew()
|
||||
(STR #2)</LI>
|
||||
<LI>mxmlEntityAddCallback() now returns an integer status (STR #2)</LI>
|
||||
<LI>Added UTF-16 support (input only; all output is UTF-8)</LI>
|
||||
<LI>Added index functions to build a searchable index of XML nodes.</LI>
|
||||
<LI>Added character entity callback interface to support additional
|
||||
@ -1681,7 +1964,7 @@ mxmlElementSetAttr(
|
||||
<P>Add a callback to convert entities to Unicode.</P>
|
||||
<H4>Syntax</H4>
|
||||
<PRE>
|
||||
void
|
||||
int
|
||||
mxmlEntityAddCallback(
|
||||
int (*cb)(const char *name));
|
||||
</PRE>
|
||||
@ -1695,7 +1978,7 @@ mxmlEntityAddCallback(
|
||||
add</TD></TR>
|
||||
</TABLE>
|
||||
<H4>Returns</H4>
|
||||
<P>Nothing.</P>
|
||||
<P>0 on success, -1 on failure</P>
|
||||
|
||||
<!-- NEW PAGE -->
|
||||
<H3><A name="mxmlEntityGetName">mxmlEntityGetName()</A></H3>
|
||||
|
BIN
www/mxml.pdf
BIN
www/mxml.pdf
Binary file not shown.
BIN
www/mxml.ps.gz
BIN
www/mxml.ps.gz
Binary file not shown.
Loading…
Reference in New Issue
Block a user