xml_string: Writing XML data to strings in memory

Previous: xml_write: Writing XML data to disk ] [ Top: index ] [ Next: xml_prepend: Inserting elements ]

(March 30, 2001): It's taken me a long time to get to this in C (the Perl XMLAPI had this right from day one) but boy have I wanted it a lot! It does the obvious: instead of writing the XML to a stream, it builds a malloc'd string buffer instead. The caller must free the buffer. Just as with the stream writer, we have a regular version and one which just writes the content of the element given (useful for retrieving the content of text-only elements.)

Just to make things easy, our functions allocate in 256-byte blocks. Most of the work is done in the helper functions _xml_string_tackon and _xml_string_append. The first takes a buffer and a string to add to it, and grows the buffer if necessary before appending the data. The second does the work of moving through the XML tree to build the return buffer.
 
char * _xml_string_tackon (char * buffer, int * cursize, int * curptr, char * data)
{
   int len = strlen (data);
   if (len + *curptr > *cursize) {
      *cursize += 256;
      buffer = (char *) realloc ((void *) buffer, *cursize);
   }
   *curptr += len;
   strcat (buffer, data);
   return (buffer);
}

char * _xml_string_append (char * buffer, int * cursize, int * curptr, XML * xml)
{
   ATTR * attr;
   ELEMENTLIST * list;

   if (xml->name == NULL) {
      buffer = _xml_string_tackon (buffer, cursize, curptr, xml->attrs->value);
      return (buffer);
   }

   buffer = _xml_string_tackon (buffer, cursize, curptr, "<");
   buffer = _xml_string_tackon (buffer, cursize, curptr, xml->name);
   attr = xml->attrs;
   while (attr != NULL) {
      buffer = _xml_string_tackon (buffer, cursize, curptr, " ");
      buffer = _xml_string_tackon (buffer, cursize, curptr, attr->name);
      buffer = _xml_string_tackon (buffer, cursize, curptr, "=\"");
      buffer = _xml_string_tackon (buffer, cursize, curptr, attr->value);
      buffer = _xml_string_tackon (buffer, cursize, curptr, "\"");
      attr = attr->next;
   }

   if (xml->children == NULL) {
      buffer = _xml_string_tackon (buffer, cursize, curptr, "/>");
      return (buffer);
   } else buffer = _xml_string_tackon (buffer, cursize, curptr, "/>");

   list = xml->children;
   while (list) {
      buffer = _xml_string_append (buffer, cursize, curptr, list->element);
      list = list->next;
   }

   buffer = _xml_string_tackon (buffer, cursize, curptr, "</");
   buffer = _xml_string_tackon (buffer, cursize, curptr, xml->name);
   buffer = _xml_string_tackon (buffer, cursize, curptr, ">");

   return (buffer);
}

char * xml_string (XML * xml)
{
   char * ret;
   int cursize;
   int curptr;

   ret = (char *) malloc (256);
   *ret = '\0';
   cursize = 256;
   curptr = 0;

   return (_xml_string_append (ret, &cursize, &curptr, xml));
}


char * xml_stringcontent (XML * xml)
{
   char * ret;
   int cursize;
   int curptr;
   ELEMENTLIST * list;

   ret = (char *) malloc (256);
   *ret = '\0';
   cursize = 256;
   curptr = 0;

   list = xml->children;
   while (list) {
      ret = _xml_string_append (ret, &cursize, &curptr, list->element);
      list = list->next;
   }

   return (ret);
}
Previous: xml_write: Writing XML data to disk ] [ Top: index ] [ Next: xml_prepend: Inserting elements ]


This code and documentation are released under the terms of the GNU license. They are additionally copyright (c) 2000, Vivtek. All rights reserved except those explicitly granted under the terms of the GNU license. This presentation was created using LPML.