读取一个格式良好的XML文档(只能包含标记和内容),并按层次编号并输出。

  1. #include <stdio.h>
  2. #include <memory.h>
  3. #include <string.h>
  4. #include <ctype.h>
  5. #define BUFSIZE 30
  6. //XML文档结点
  7. struct Node
  8. {
  9.     int num;    //结点编号
  10.     char name[BUFSIZE]; //结点名
  11.     char value[BUFSIZE]; //结点值
  12.     Node *parent; //父结点;
  13.     Node *lsibling; //左同胞结点
  14.     Node *rsibling; //右同胞结点
  15.     Node *firstChild; //第一个子结点
  16.     Node *lastChild; //最后一个子结点
  17.     int childCount; //子结点个数,这个可以不要,有这个要方便些,在插入和删除子结点时要维护
  18. };
  19. //从文件中读一个字符串,直到读到标记符为此
  20. void ReadString(FILE *fp, char *buf)
  21. {
  22.     char ch;
  23.     char *p = buf;
  24.     ch = fgetc(fp);
  25.     do
  26.     {
  27.         if (p != buf || !isspace(ch)) //自动去掉首部空白
  28.         {
  29.             *(p++) = ch;
  30.         }
  31.         ch = fgetc(fp);
  32.     }while (!feof(fp) && (ch != '<' && ch != '>' || p == buf));
  33.     if ('<' == ch) //下一个标记开始
  34.     {
  35.         fseek(fp, -1, SEEK_CUR);
  36.         p--;
  37.     }
  38.     else if ('>' == ch) 
  39.     {
  40.         *p = ch;
  41.     }
  42.     //以下代码为去掉buf的尾空白
  43.     while (p != buf && isspace(*p)) p--;
  44.     *(++p) = '/0';
  45. }
  46. //从文件中读取一个结点及其所有子结点
  47. void ReadNode(FILE *fp, Node *node)
  48. {
  49.     char buf[BUFSIZE];
  50.     Node *child = NULL; //当前子结点
  51.     ReadString(fp, buf); //读入开始标记
  52.     strcpy(node->name, &buf[1]);  //只拷贝标记正文
  53.     node->name[strlen(node->name) - 1] = '/0';
  54.     while (1)
  55.     {
  56.         buf[0] = '/0';
  57.         ReadString(fp, buf); //读入下一个字符串
  58.         if ('<' == buf[0]) //读到标记
  59.         {
  60.             if ('/' == buf[1]) //是结束标记
  61.             {
  62.                 break//本层结束
  63.             }
  64.             else //遇到开始标记,是子结点
  65.             {
  66.                 Node *p = new Node;
  67.                 memset(p, 0, sizeof(Node));
  68.                 p->parent = node;
  69.                 if (child) //如果当前子结点不为空
  70.                 {
  71.                     child->rsibling = p;
  72.                     p->lsibling = child;
  73.                 }
  74.                 else //为第一个子结点
  75.                 {
  76.                     node->firstChild = p;
  77.                 }
  78.                 fseek(fp, -(long)strlen(buf), SEEK_CUR); //将文件指针拨回开始标记之前
  79.                 ReadNode(fp, p);
  80.                 child = p;
  81.                 node->childCount ++; //子结点个数加一
  82.             }
  83.         }
  84.         else //是结点值
  85.         {
  86.             strcpy(node->value, buf);
  87.         }
  88.     }
  89.     node->lastChild = child; //最后一个子结点
  90. }
  91. //按层次访问所有结点并编号
  92. void GetNum(Node *node)
  93. {
  94.     static int num = 1;
  95.     if (!node) return;
  96.     node->num = num++;
  97.     if (node->rsibling) //本层还未结束
  98.         GetNum(node->rsibling);
  99.     else if (node->parent)
  100.     {
  101.         if (node->parent->rsibling) //找到右堂兄弟
  102.             GetNum(node->parent->rsibling->firstChild);
  103.         else //进下一层
  104.             GetNum(node->parent->firstChild->firstChild);
  105.     }
  106.     else //本结点是根结点,直接进入下一层
  107.         GetNum(node->firstChild);
  108. }
  109. //按层次打印所有结点
  110. void PrintNode(Node *node)
  111. {
  112.     if (!node) return;
  113.     printf("Element %d - %s: %s, child:"
  114.         node->num, node->name, 
  115.         strlen(node->value) ? node->value : "null");
  116.     Node *p = node->firstChild;
  117.     if (!p) printf("null");
  118.     while (p)
  119.     {
  120.         printf("Element %d", p->num);
  121.         p = p->rsibling;
  122.         if (p) printf(", ");
  123.     }
  124.     printf("/n");
  125.     if (node->rsibling) //本层还未结束
  126.         PrintNode(node->rsibling);
  127.     else if (node->parent)
  128.     {
  129.         if (node->parent->rsibling) //找到右堂兄弟
  130.             PrintNode(node->parent->rsibling->firstChild);
  131.         else //进下一层
  132.             PrintNode(node->parent->firstChild->firstChild);
  133.     }
  134.     else //本结点是根结点,直接进入下一层
  135.         PrintNode(node->firstChild);
  136. }
  137. //释放结点树
  138. void FreeNode(Node *node)
  139. {
  140.     Node *p = node->firstChild;
  141.     while (p)
  142.     {
  143.         Node *q = p->rsibling;
  144.         FreeNode(p);
  145.         p = q;
  146.     }
  147.     delete node;
  148. }
  149. void main()
  150. {
  151.     char filename[BUFSIZE];
  152.     FILE *fp;
  153.     printf("Please enter XML filename:");
  154.     scanf("%s", filename);
  155.     if (!(fp = fopen(filename, "r")))
  156.     {
  157.         printf("Open file %s fail!/n");
  158.     }
  159.     else
  160.     {
  161.         Node *node = new Node;
  162.         memset(node, 0, sizeof(Node));
  163.         ReadNode(fp, node);
  164.         fclose(fp);
  165.         GetNum(node);
  166.         PrintNode(node);
  167.         FreeNode(node);
  168.     }
  169. }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值