Solved

parse a template file

Posted on 2000-02-24
9
347 Views
Last Modified: 2010-04-02
Hi,

This is what I want to achieve:

I have a text file as following:
=====================================
<html>
<body>
  Name:<$MY_TAG FIELD=name>
  TEL :<$MY_TAG FIELD=tel>
</body>
</html>
=====================================
I want to write a c program that read in this template file and replace <$MY_TAG ??????> with the data I retrieved from a database. And then prints out this file.

Can someone please tell me what's the good algorithm to use? Should I read this file into memory first and processes it from there.
Or is there any third-party C library that can help me do this?

Thanks in advance.

0
Comment
Question by:samantha
  • 3
  • 2
  • 2
  • +2
9 Comments
 
LVL 3

Expert Comment

by:ufolk123
ID: 2557081
Hi samantha,

I do not feel this problem as that of a parsing problem .May be the reverse and correct logic of your problem is to read out an array of name and tel pairs and generate the an output in the form of template

<html>
<body>
  Name:<$MY_TAG FIELD=name>
  TEL :<$MY_TAG FIELD=tel>
</body>
</html>

So you do it this way,
Read each record from the database and
write a code genrerator(so called) which will take in ( name1,telno1) and print the result in the form of

<html>
<body>
  Name:<$MY_TAG FIELD=name1>
  TEL :<$MY_TAG FIELD=tel1>
</body>
</html>

This you acheive simple by a series of printfs.
printf("<html> \n <body> \n   Name:<$MY_TAG FIELD=");
printf("%s",name1);
printf(>TEL :<$MY_TAG FIELD=");
printf("%s",tel1);
printf("> \n </body> \n</html> ");

0
 

Author Comment

by:samantha
ID: 2558328
Hi ufolk123,

Thanks for the answer. But that's not what I want. Maybe I didn't state the problem clearly. This is actually a CGI program.

Let's call this program test.c. And the template file template.txt:
=============================
<html>
<body>
  Name:<$MY_TAG FIELD=name>
  TEL :<$MY_TAG FIELD=phone>
</body>
</html>
=============================

And a database table like this:
==============================
ID       NAME        PHONE
01       Samantha    (111)111-1111
02       ufolk123    (222)222-2222
......
==============================

The program is invoked like this:

http://xx.com/test.exe?id=02&template= template.txt

This program then retrieves the Record 02 from the database and use the "template.txt" to generate the following result page:
=============================
<html>
<body>
  Name:ufolk123
  TEL :(222)222-2222
</body>
</html>
=============================

I don't want to hard code this file using printf() beacuse everytime you want to change the layout, you have to do it inside the code and recompile the program. With this template file, users of "test.exe" can always provide their own "template.txt".

Thanks,

0
 

Expert Comment

by:DontPanic
ID: 2558686
Hmmm. Looks like a problem better suited to XML.
0
 
LVL 3

Expert Comment

by:arnond
ID: 2558895
I would use a kind of final state machine that will parse the input file.
I would read the input file char by char and look first, for a '<' then I 'd look of a '$', 'M', 'Y','_' etc....untill i get the string '<$MY_TAG FIELD=' now, I know that the following string (up to the next '>') is the requiered field. After knowing wat field it is, just use the database's interface as you normaly do.
BTW, while you look for the first '<' just read the char and output it if it's not '<'. Your code should look something like this:
----------------------------
char ch,needed_ch,temp_array[100];
int state=0; /* state will record the state of the FSM (i.e., how many chars we've read so far that match the string we're looking for.*/
FILE* in_file,out_file; /* assuming files are open...*/

while ((ch=getc(infile))!=EOF)
{
  switch (state)
  {
     case (0):
       needed_ch='<';
       break;
     case (1):
       needed_ch='$';
       break;
     case (2):
       needed_ch='M';
       break;
/* continue with cases */
  }
  if (ch==needed_ch) /* did we get what we wanted ? */
  {
     temp_array[state]=ch;
     temp_array[state+1]='\0'; /* terminating NULL*/
     if (state==MAX_NUM_OF_STATES) /* which is the length of '<$MY_TAG FIELD' */
     {
        /* do data base stuff here and output the correct field's value */
     }
  }  else /* didn't get what we wanted.*/
     {
       putc (ch,out_file); /* just output the given char*/
       state=0; /* start over*/
     }
}

----------------------------
Please note that this code wasn't tested and compiled so it may have some erros but it should give you a clear idea.

Arnon David.
0
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 
LVL 11

Accepted Solution

by:
alexo earned 100 total points
ID: 2559065
Normally, this is a job for Lex/Yacc.
But since you want it in C, do something like the following:
(quick & dirty: no error checking performed, file names are constants...)

    #include <stdio.h>
    #include <string.h>

    #define IN "in.txt"
    #define OUT "out.txt"
    #define MAX_LEN 256
    #define TOKEN1 "<$MY_TAG FIELD="
    #define TOKEN2 '>'

    FILE* in = fopen(IN, "r");
    FILE* out = fopen(OUT, "w");
    char line[MAX_LEN];

    while (fgets(line, sizeof line, in))
    {
        char* p1 = strstr(line, TOKEN1);
        if (p1)
        {
            char value[MAX_LEN];
            char* field = strdup(p1 + sizeof TOKEN1);
            char* p2 = strchr(field, TOKEN2);
            *p1 = *p2 = 0;
    /*
            Now, 'field' contains the name of the desired
            field name.  You get it's value from the DB
            into the 'value' variable.
    */
            strcat(p1, value);
            strcat(p1, p2 + 1);
        }

        fputs(line, out);
    }

    fclose(in);
    fclose(out);
0
 

Author Comment

by:samantha
ID: 2559500
Thanks a lot, guys.

arnond & alexo, both your answers are excellent.  I wish they had a way to let me split the points to both of you.

Since alexo has locked it, I am giving the points to him.  Sorry, arnond. But if you can tell me how I can give you the points, I will also give 100 points.

Thanks again.  

0
 
LVL 3

Expert Comment

by:arnond
ID: 2559691
If you want to spend an extra 100 points, just post another (empty) question titled something like "points for arnond" and I'll "answer" it and you'll accept.
But, do that only if you want to.

Thanks,
Arnon David.
0
 
LVL 11

Expert Comment

by:alexo
ID: 2561309
If you don't have enough points, I can give Arnon 100+A of my own (I got some spare since I rarely ask questions).  Post a comment here in case you like the idea.
0
 
LVL 3

Expert Comment

by:arnond
ID: 2561355
it's ok, she already posted one.

thanks anyway,
Arnon David.
0

Featured Post

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

An Outlet in Cocoa is a persistent reference to a GUI control; it connects a property (a variable) to a control.  For example, it is common to create an Outlet for the text field GUI control and change the text that appears in this field via that Ou…
Summary: This tutorial covers some basics of pointer, pointer arithmetic and function pointer. What is a pointer: A pointer is a variable which holds an address. This address might be address of another variable/address of devices/address of fu…
The goal of this video is to provide viewers with basic examples to understand how to use strings and some functions related to them in the C programming language.
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use nested-loops in the C programming language.

759 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now