2

I m playing with minixml in my C program. And when I save The minixml tree into a file with the mxmlSaveFile(bkp_tree, fp, MXML_NO_CALLBACK); function I get the whole xml data in one bloc . There is no organization in displaying the xml structure in the file (New line, indent...).

The xml data is saved in this way

<B1><BB1>BBB1</BB1></B1><B2><BB2>BBB2</BB2></B2><B3><BB3>BBB3</BB3></B3>

How to make the minixml saving the xml data in the following way ?

<B1>
    <BB1>BBB1</BB1>
</B1>
<B2>
    <BB2>BBB2</BB2>
</B2>
<B3>
    <BB3>BBB3</BB3>
</B3>
MOHAMED
  • 41,599
  • 58
  • 163
  • 268

2 Answers2

2

Instead of giving MXML_NO_CALLBACK, you can give a callback which returns what whitespace should be printed before and after each element. See the documentation of mxmlSaveFile.

What the callback basically receives is each node that is about to be printed with an additional argument in one of the four possible values of MXML_WS_BEFORE/AFTER_OPEN/CLOSE. In either of these cases, you should decide how the whitespace before or after this opening or closing node should be.

An example that (I hope) outputs what you want is the following:

static const char *_xml_whitespace_callback(mxml_node_t *node, int where)
{
    const char *name = node->value.element.name;

    if (node->type != MXML_ELEMENT)
        return NULL;
    if (name == NULL)
        return NULL;

    switch (where)
    {
    case MXML_WS_BEFORE_OPEN:
        if (strcmp(name, "B1") == 0
                || strcmp(name, "B2") == 0)
                || strcmp(name, "B3") == 0))
            return NULL;
        if (strcmp(name, "BB1") == 0
                || strcmp(name, "BB2") == 0)
                || strcmp(name, "BB3") == 0))
            return "\t";
        return NULL;
    case MXML_WS_AFTER_OPEN:
        if (strcmp(name, "B1") == 0
                || strcmp(name, "B2") == 0)
                || strcmp(name, "B3") == 0))
            return "\n";
        if (strcmp(name, "BB1") == 0
                || strcmp(name, "BB2") == 0)
                || strcmp(name, "BB3") == 0))
            return NULL;
        return NULL;
    case MXML_WS_BEFORE_CLOSE:
        return NULL;
    case MXML_WS_AFTER_CLOSE:
        return "\n";
    default:
        return NULL;
    }
}
Shahbaz
  • 46,337
  • 19
  • 116
  • 182
2

Copied from minixml documentation :

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 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:

const char *
whitespace_cb(mxml_node_t *node,
              int where)
{
  const char *name;

 /*
  * We can conditionally break to a new line
  * before or after any element. These are
  * just common HTML elements...
  */

  name = mxmlGetElement(node);

  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);
}

To use this callback function, simply use the name when you call any of the save functions:

FILE *fp;
mxml_node_t *tree;

fp = fopen("filename.xml", "w");
mxmlSaveFile(tree, fp, whitespace_cb);
fclose(fp);
developer
  • 4,744
  • 7
  • 40
  • 55