2

我在我的 C 程序中使用 minixml。当我将 minixml 树保存到具有该mxmlSaveFile(bkp_tree, fp, MXML_NO_CALLBACK);功能的文件中时,我将整个 xml 数据放在一个 bloc 中。在文件中显示 xml 结构时没有组织(新行,缩进...)。

xml数据就是这样保存的

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

如何使 minixml 以下列方式保存 xml 数据?

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

2 回答 2

2

minixml 文档复制:

对于每个元素节点,您的回调函数最多会被调用四次,并带有一个指向该节点的指针和一个“where”值MXML_WS_BEFORE_OPENMXML_WS_AFTER_OPENMXML_WS_BEFORE_CLOSEMXML_WS_AFTER_CLOSE。如果不应添加空格,则回调函数应返回,否则应返回NULL要插入的字符串(空格、制表符、回车和换行符)。

以下空白回调可用于向 XHTML 输出添加空白,使其在标准文本编辑器中更具可读性:

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

要使用此回调函数,只需在调用任何保存函数时使用名称:

FILE *fp;
mxml_node_t *tree;

fp = fopen("filename.xml", "w");
mxmlSaveFile(tree, fp, whitespace_cb);
fclose(fp);
于 2013-01-23T15:13:28.863 回答
2

除了给MXML_NO_CALLBACK,你可以给一个回调,它返回每个元素之前和之后应该打印的空白。请参阅 的文档mxmlSaveFile

回调基本上接收的是即将打印的每个节点,其中包含四个可能值之一中的附加参数MXML_WS_BEFORE/AFTER_OPEN/CLOSE。在任何一种情况下,您都应该决定这个打开或关闭节点之前或之后的空白应该如何。

(我希望)输出您想要的示例如下:

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;
    }
}
于 2013-01-23T13:56:30.417 回答