从C中的XML文件获取相同多个标签之间的所有信息

时间:2015-07-06 06:46:58

标签: c xml parsing

要点:

  • 我开发了一个应用程序,它应该:读取 XML文件不使用使用任何XML库),在特定标记之间获取一些单词并在屏幕使用基本printf()

我的 XML文件如下所示:

<Server>  
    <Host>ip1</Host>  
    <User>user1</User>  
    <Pass>pass1</Pass>  
</Server>  
<Server>  
    <Host>ip2</Host>  
    <User>user2</User>  
    <Pass>pass2</Pass>  
</Server>

现在,我的代码能够获得: ip1,user1,pass1

如何修改我的代码,以便我也可以 ip2,user2,pass2 然后 ip3,user3,pass3 等等,直到我到达结尾文件?

代码是下一个:

int getContent()
{
    //variables for reading the XML file
    char *buffer=0;
    long length;
    FILE *xmlFile=fopen("C:/Users/IEUser/AppData/Roaming/recentservers.xml","r");

    //constants for parsing XML
    const char *HOSTSTART = "<Host>";
    const char *HOSTEND = "</Host>";

    const char *USERSTART = "<User>";
    const char *USEREND = "</User>";

    const char *PASSSTART = "<Pass encoding=\"base64\">";
    const char *PASSEND = "</Pass>";

    char *target_host = NULL,*target_user = NULL,*target_pass = NULL, *start, *end;

    //read the xml file
    if(xmlFile)
    {
        fseek(xmlFile,0,SEEK_END);
        length=ftell(xmlFile);
        fseek(xmlFile,0,SEEK_SET);

        buffer=malloc(length);
        if(buffer)
        {
            fread(buffer,1,length,xmlFile);
        }
        fclose(xmlFile);
    }

    //get the HOST
    if(buffer)
    {
        if(start=strstr(buffer,HOSTSTART))
        {
            start += strlen(HOSTSTART);
            if(end=strstr(start, HOSTEND))
            {
                target_host = (char *)malloc(end-start+1);
                memcpy(target_host,start,end-start);
                target_host[end-start]='\0';
            }
        }
        if(target_host)
            printf("%s\n",target_host);
        //free(target_host);
    }

    //get the USER
    if(buffer)
    {
        if(start=strstr(buffer,USERSTART))
        {
            start += strlen(USERSTART);
            if(end=strstr(start, USEREND))
            {
                target_user = (char *)malloc(end-start+1);
                memcpy(target_user,start,end-start);
                target_user[end-start]='\0';
            }
        }
        if(target_user)
            printf("%s\n",target_user);
        //free(target_user);
    }

    //get the PASS
    if(buffer)
    {
        if(start=strstr(buffer,PASSSTART))
        {
            start += strlen(PASSSTART);
            if(end=strstr(start, PASSEND))
            {
                target_pass = (char *)malloc(end-start+1);
                memcpy(target_pass,start,end-start);
                target_pass[end-start]='\0';
            }
        }
        if(target_pass)
            printf("%s\n",target_pass);
        //free(target_pass);
    }
    // here I would like a for which will printf as many target information as they are in that XML File
    printf("%s | %s | %s",target_host,target_user,target_pass);
    printf("\n\n");
    return 0;
}

int main()
{
    getContent();
    return 0;
}

// EDIT1:

int readTag(char *buffer, const char *tagStart, const char *tagEnd){
    int start, end;
    char *target = NULL;
    start = 0;
    end = 0;
    if(start=strstr(buffer,tagStart))
    {
        start += strlen(tagStart);
        if(end=strstr(start, tagEnd))
        {
            target = malloc(end-start+1); //don't cast malloc
            memcpy(target,start,end-start);
            target[end-start]='\0';
            printf("Target between tag %s and %s = %s", tagStart, tagEnd, target);
            //sendTargetToGET(tagStart, tagEnd, target);
            free(target);
        }
    }
    return (end - start); // returns nr characters between the tags
}

int getTagID(char *buffer){
    const char *HOSTSTART = "<Host>";
    const char *HOSTEND = "</Host>";

    const char *USERSTART = "<User>";
    const char *USEREND = "</User>";

    const char *PASSSTART = "<Pass encoding=\"base64\">";
    const char *PASSEND = "</Pass>";

    if(strstr(buffer, HOSTSTART) != NULL && strstr(buffer, HOSTEND) != NULL)
    {
        return 1;
    }
    else if(strstr(buffer, USERSTART) != NULL && strstr(buffer, USEREND) != NULL)
    {
        return 2;
    }
    else if(strstr(buffer, PASSSTART) != NULL && strstr(buffer, PASSEND) != NULL)
    {
        return 3;
    }
    else 
        return 0;
}

int main()
{
    char *buffer=0;

    const char *HOSTSTART = "<Host>";
    const char *HOSTEND = "</Host>";

    const char *USERSTART = "<User>";
    const char *USEREND = "</User>";

    const char *PASSSTART = "<Pass encoding=\"base64\">";
    const char *PASSEND = "</Pass>";
    FILE *xmlFile=fopen("C:/Users/IEUser/AppData/Roaming/recentservers.xml","r");

    int tagID = 0;
    while (fgets(buffer, sizeof(buffer), xmlFile) != NULL)
    {
         tagID = getTagID(buffer);

         if(tagID == 1)
         {
             readTag(buffer, HOSTSTART, HOSTEND);
         }
         else if(tagID == 2)
         {
             readTag(buffer, USERSTART, USEREND);
         }
         else if(tagID == 3)
         {

         }
    }
    return 0;
}

遗憾的是,我有一个断言失败,我不知道是什么原因

1 个答案:

答案 0 :(得分:2)

我建议的是:

1)将标记读取部分放在函数中,这样您就不能为每个标记使用相同的代码:

int readTag(char *buffer, const char *tagStart, const char *tagEnd){
    int start, end;
    char *target = NULL;
    start = 0;
    end = 0;
    if(start=strstr(buffer,tagStart))
    {
        start += strlen(tagStart);
        if(end=strstr(start, tagEnd))
        {
            target = malloc(end-start+1); //don't cast malloc
            memcpy(target,start,end-start);
            target[end-start]='\0';
            printf("Target between tag %s and %s = %s", tagStart, tagEnd, target);
            //sendTargetToGET(tagStart, tagEnd, target);
            free(target);
        }
    }
    return (end - start); // returns nr characters between the tags
}

2)逐行读取文件,检查该行是否包含您需要的标签(可能带有功能)并调用相关的标签读取功能。

int tagID = 0;
while (fgets(buffer, sizeof(buffer), xmlFile) != NULL){
     tagID = getTagID(buffer);

     if(tagID == 1){//or use an enum here
         readTag(buffer, HOSTSTART, HOSTEND);
     }else if(tagID == 2){
         readTag(buffer, USERSTART, USEREND);
     }else if(tagID == 3){ //and so on
     }
}

int getTagID(char *buffer){
    if(strstr(buffer, HOSTSTART) != NULL && strstr(buffer, HOSTEND) != NULL){
        return 1;
    }else if(strstr(buffer, USERSTART) != NULL && strstr(buffer, USERSTART) != NULL){
        return 2;
    }else if(/*and so on*/){
    }else return 0;
}