Cajuu'
Cajuu'

Reputation: 1166

Get all information between the same multiple tags from XML file in C

Summary:

My XML File looks like this:

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

Now, my code is able to get: ip1, user1, pass1.

How can I modify my code, so that I can also get ip2, user2, pass2 then ip3, user3, pass3 and so on until I reach the end of the file ?

The code is the next one:

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

I've got an assertion failure unfortunately and I don't know what is the reason

Upvotes: 1

Views: 126

Answers (1)

moffeltje
moffeltje

Reputation: 4659

What I would suggest is:

1) Put the tag read parts in a function so you can don't have the same code for every tag:

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) Read the file line by line, check if the line contains tags you need (maybe with a function) and call the associated tag read function.

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

Upvotes: 2

Related Questions