讀取一個格式良好的XML文檔,并按層次編號并輸出

字號:

#include
    #include
    #include
    #include
    #define BUFSIZE 30
    //XML文檔結(jié)點
    struct Node
    {
    int num; //結(jié)點編號
    char name[BUFSIZE]; //結(jié)點名
    char value[BUFSIZE]; //結(jié)點值
    Node *parent; //父結(jié)點;
    Node *lsibling; //左同胞結(jié)點
    Node *rsibling; //右同胞結(jié)點
    Node *firstChild; //第一個子結(jié)點
    Node *lastChild; //最后一個子結(jié)點
    int childCount; //Examda提示: 子結(jié)點個數(shù),這個可以不要,有這個要方便些,在插入和刪除子結(jié)點時要維護(hù)
    };
    //從文件中讀一個字符串,直到讀到標(biāo)記符為此
    void ReadString(FILE *fp, char *buf)
    {
    char ch;
    char *p = buf;
    ch = fgetc(fp);
    do
    {
    if (p != buf || !isspace(ch)) //自動去掉首部空白
    {
    *(p++) = ch;
    }
    ch = fgetc(fp);
    }while (!feof(fp) && (ch != '<' && ch != '>' || p == buf));
    if ('<' == ch) //下一個標(biāo)記開始
    {
    fseek(fp, -1, SEEK_CUR);
    p--;
    }
    else if ('>' == ch)
    {
    *p = ch;
    }
    //以下代碼為去掉buf的尾空白
    while (p != buf && isspace(*p)) p--;
    *(++p) = '\0';
    }
    //從文件中讀取一個結(jié)點及其所有子結(jié)點
    void ReadNode(FILE *fp, Node *node)
    {
    char buf[BUFSIZE];
    Node *child = NULL; //當(dāng)前子結(jié)點
    ReadString(fp, buf); //讀入開始標(biāo)記
    strcpy(node->name, &buf[1]); //只拷貝標(biāo)記正文
    node->name[strlen(node->name) - 1] = '\0';
    while (1)
    {
    buf[0] = '\0';
    ReadString(fp, buf); //讀入下一個字符串
    if ('<' == buf[0]) //讀到標(biāo)記
    {
    if ('/' == buf[1]) //是結(jié)束標(biāo)記
    {
    break; //本層結(jié)束
    }
    else //遇到開始標(biāo)記,是子結(jié)點
    {
    Node *p = new Node;
    memset(p, 0, sizeof(Node));
    p->parent = node;
    if (child) //如果當(dāng)前子結(jié)點不為空
    {
    child->rsibling = p;
    p->lsibling = child;
    }
    else //為第一個子結(jié)點
    {
    node->firstChild = p;
    }
    fseek(fp, -(long)strlen(buf), SEEK_CUR); //將文件指針撥回開始標(biāo)記之前
    ReadNode(fp, p);
    child = p;
    node->childCount ++; //子結(jié)點個數(shù)加一
    }
    }else //是結(jié)點值
    {
    strcpy(node->value, buf);
    }
    }
    node->lastChild = child; //最后一個子結(jié)點
    }
    //按層次訪問所有結(jié)點并編號
    void GetNum(Node *node)
    {
    static int num = 1;
    if (!node) return;
    node->num = num++;
    if (node->rsibling) //本層還未結(jié)束
    GetNum(node->rsibling);
    else if (node->parent)
    {
    if (node->parent->rsibling) //找到右堂兄弟
    GetNum(node->parent->rsibling->firstChild);
    else //進(jìn)下一層
    GetNum(node->parent->firstChild->firstChild);
    }
    else //本結(jié)點是根結(jié)點,直接進(jìn)入下一層
    GetNum(node->firstChild);
    }
    //按層次打印所有結(jié)點
    void PrintNode(Node *node)
    {
    if (!node) return;
    printf("Element %d - %s: %s, child:",
    node->num, node->name,
    strlen(node->value) ? node->value : "null");
    Node *p = node->firstChild;
    if (!p) printf("null");
    while (p)
    {
    printf("Element %d", p->num);
    p = p->rsibling;
    if (p) printf(", ");
    }
    printf("\n");
    if (node->rsibling) //本層還未結(jié)束
    PrintNode(node->rsibling);
    else if (node->parent)
    {
    if (node->parent->rsibling) //找到右堂兄弟
    PrintNode(node->parent->rsibling->firstChild);
    else //進(jìn)下一層
    PrintNode(node->parent->firstChild->firstChild);
    }
    else //本結(jié)點是根結(jié)點,直接進(jìn)入下一層
    PrintNode(node->firstChild);
    }
    //釋放結(jié)點樹
    void FreeNode(Node *node)
    {
    Node *p = node->firstChild;
    while (p)
    {
    Node *q = p->rsibling;
    FreeNode(p);
    p = q;
    }
    delete node;
    }
    void main()
    {
    char filename[BUFSIZE];
    FILE *fp;
    printf("Please enter XML filename:");
    scanf("%s", filename);
    if (!(fp = fopen(filename, "r")))
    {
    printf("Open file %s fail!\n");
    }
    else
    {
    Node *node = new Node;
    memset(node, 0, sizeof(Node));
    ReadNode(fp, node);
    fclose(fp);
    GetNum(node);
    PrintNode(node);
    FreeNode(node);
    }
    }