Lack of symmetry: How to create XML

Egil Kvaleberg <[email protected]> Mon, 05 Jul 2010 14:32:58 +0200
Newsgroups gmane.text.xml.expat.general
Message-ID <[email protected]>
It has always occurred to me that while eXpat is a very elegant and
simple solution to the task of parsing XML, AFAIK no parallel and
obvious way of generating XML exists. When the questions is raised, I
often see it suggested that one employs a "DIY" approach of generating
XML through fscanf() or similar. While the task of generating XML is
much more trivial than parsing, use of fscanf() is at best highly
inelegant and un-symmetric. Even worse is that it introduces the user to
problems of escaping characters and handling of character encoding and
syntactic correctness that XML really was intended to isolate you from
in the first place.

So, without further ado, let me hereby suggest that eXpat is extended by
a very lightweight set of functions to also generate XML. The additional
overhead to the existing library is in fact entirely minimal.

If there is interest, I would be more than happy to submit some code.
The suggestion below I believe follows the ideas of the simplicity of
the parsing side. There is one callback handler that is invoked at any
time the buffer should be flushed, and the generator functions are
entirely straight forward. This suggestion is for the very basic of
functions, support for more sophisticated functions can readily be added
later.

Sincerely,

Egil

----------------------------------CUT
HERE-----------------------------------

struct XML_GenStruct;
typedef struct XML_GenStruct *XML_Generator;

/* XML generator buffer handler.
   Will be called whenever a buffer is ready.
   userData is as defined by XML_GenUserData(), or NULL by default.
   isFinal is set for the final buffer, no further calls will be done.
   len may in some cases be zero.
*/
typedef void
(*XML_GenBufferHandler)(XML_Generator g, void *userData,
                        const char *s, int len, int isFinal);

/* Create an XML generator, specifying a buffer handler.
   If len is NULL, a buffer of size buflen will be allocated
   and managed for you.
   Otherwise, the buffer you provide can only be released after
XML_GenFree() has returned.
*/
XML_Generator XML_GenCreate(const XML_Char* encoding,
                            XML_GenBufferHandler genbuf,
                            char *buf,
                            int buflen);

/* XML generator done.
   After this, XML_Generator g must not be used
*/
void XML_GenFree(XML_Generator g);

/* Generate a starting element. Must always be paired with a
   subsequent XML_GenEndElement()
*/
void XML_GenStartElement(XML_Generator g,
                         const XML_Char *name);

/* Generate an attribute pair for immediately preceding
XML_GenStartElement().
   Call once for every attribute.
*/
void XML_GenElementAttribute(XML_Generator g,
                             const XML_Char *attr_name,
                             const XML_Char *attr_value);

/* Generate character data for XML_GenStartElement().
   May be called more than once.
*/
void XML_GenCharacterData(XML_Generator g,
                          const XML_Char *s);

/* End element generation.
   Name must be the same as for the XML_GenStartElement() call
*/
void XML_GenEndElement(XML_Generator g,
                       const XML_Char *name);

/* Insert a comment into the XML.
*/
void XML_GenComment(XML_Generator g,
                    const XML_Char *cmnt);

/* Specify the userData for XML generator.
*/
void XML_GenUserData(XML_Generator g, void *userData);

 
----------------------------------CUT
HERE-----------------------------------




-- 
Company: Kvaleberg AS
Office: +47 22 44 31 75
Mobile: +47 920 22 780
Fax: +47 22 44 46 77
Web: http://www.kvaleberg.com/