如何使 minixml 数据的表示更具可读性

How to make the presentation of minixml data more readble?

本文关键字:可读性 表示 何使 minixml 数据      更新时间:2023-10-16

我正在我的C程序中玩minixml。当我使用 mxmlSaveFile(bkp_tree, fp, MXML_NO_CALLBACK); 函数将 minixml 树保存到一个文件中时,我将整个 xml 数据放在一个块中。在文件中显示 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>

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

而不是给出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;
    }
}