Expat, decision making on element-name

M

Maarten Verhage

Hi All,

I've made a modified version of the Expat elements.c example. What I
want the program to do is to recognize a hardcoded
element-name/tag-name and then execute some code which has access to
the data(e.g. "Maarten Verhage" in XML file).

The current situation (problem) is:

1. The XML parser calls the function startElement when it finds a tag,
in this function I don't have access to the data between the tags.

2. The XML parser calls the function charHandler when it finds data,
in this function I don't have access to the tag-name.

Thank you!

-- below is the code I have now

-- start of XML file
<?xml version="1.0"?>
<person>
<name>Maarten Verhage</name>
<age>24</age>
</person>
-- end of XML file

-- start of C file
#include <stdio.h>
#include <conio.h>
#include "expat.h"

static void XMLCALL startElement(void *userData, const char *name,
const char **atts)
{
int i;
int *depthPtr = userData;

for (i = 0; i < *depthPtr; i++)
{
putchar('\t');
}
// print elementname
puts(name);

*depthPtr += 1;
}

static void XMLCALL endElement(void *userData, const char *name)
{
int *depthPtr = userData;
*depthPtr -= 1;
}

static void XMLCALL charHandler(void *userData, const XML_Char *s, int
len)
{
int i;
for (i=0; i < len; i++)
{
fprintf(stdout, "%c", s);
}
}

int main(int argc, char *argv[])
{
FILE *xmlfile;
char buf[BUFSIZ];
XML_Parser parser = XML_ParserCreate(NULL);
int done;
int depth = 0;
XML_SetUserData(parser, &depth);
XML_SetElementHandler(parser, startElement, endElement);
XML_SetCharacterDataHandler(parser, charHandler);

// open XML file
if ((xmlfile = fopen("xml_test.xml", "r")) == NULL)
{
fprintf(stderr, "Error opening xml_test.xml\n");
getch();
return -1;
}

do
{
size_t len = fread(buf, 1, sizeof(buf), xmlfile);
done = len < sizeof(buf);
if (XML_Parse(parser, buf, len, done) == XML_STATUS_ERROR)
{
fprintf(stderr,
"%s at line %d\n",
XML_ErrorString(XML_GetErrorCode(parser)),
XML_GetCurrentLineNumber(parser));
return 1;
}
} while (!done);

XML_ParserFree(parser);

// close the XML file
fclose(xmlfile);

getch();
return 0;
}
-- end of C file
 
P

Peter Dunker

Maarten Verhage said:
Hi All,

I've made a modified version of the Expat elements.c example. What I
want the program to do is to recognize a hardcoded
element-name/tag-name and then execute some code which has access to
the data(e.g. "Maarten Verhage" in XML file).

The current situation (problem) is:

1. The XML parser calls the function startElement when it finds a tag,
in this function I don't have access to the data between the tags.

2. The XML parser calls the function charHandler when it finds data,
in this function I don't have access to the tag-name.

Thank you!


You can use other UserData, maybe a structure where depth is inside.
I never tryed it but I think that can work.

typedef struct
{
int depth;
int found;
}S_MY_DATA,*PS_MY_DATA;

-- start of XML file
<?xml version="1.0"?>
<person>
<name>Maarten Verhage</name>
<age>24</age>
</person>
-- end of XML file

-- start of C file
#include <stdio.h>
#include <conio.h>
#include "expat.h"

static void XMLCALL startElement(void *userData, const char *name,
const char **atts)
{
int i;

PS_MY_DATA pMy = userData;

for (i = 0; i < *depthPtr; i++)
{
putchar('\t');
}
// print elementname
puts(name);
//compare the name and set found to 1
*depthPtr += 1;
}

static void XMLCALL endElement(void *userData, const char *name)
{
int *depthPtr = userData;
*depthPtr -= 1;
}

static void XMLCALL charHandler(void *userData, const XML_Char *s, int
len)
{
int i;

PS_MY_DATA pMy = userData;
//if found in pMy is 1 then print and set found to 0
//or set found to 0 inside the endElement function

for (i=0; i < len; i++)
{
fprintf(stdout, "%c", s);
}
}

int main(int argc, char *argv[])
{
FILE *xmlfile;
char buf[BUFSIZ];


PS_MY_DATA pMyData;
pMyData = malloc(sizeof(S_MY_DATA));
pMyData->found = 0;
pMyData->depth = 0;
XML_Parser parser = XML_ParserCreate(NULL);
int done;

// int depth = 0;
XML_SetUserData(parser, pMyData);
^^^^^^^^
XML_SetElementHandler(parser, startElement, endElement);
XML_SetCharacterDataHandler(parser, charHandler);

// open XML file
if ((xmlfile = fopen("xml_test.xml", "r")) == NULL)
{
fprintf(stderr, "Error opening xml_test.xml\n");
getch();
return -1;
}

do
{
size_t len = fread(buf, 1, sizeof(buf), xmlfile);
done = len < sizeof(buf);
if (XML_Parse(parser, buf, len, done) == XML_STATUS_ERROR)
{
fprintf(stderr,
"%s at line %d\n",
XML_ErrorString(XML_GetErrorCode(parser)),
XML_GetCurrentLineNumber(parser));
return 1;
}
} while (!done);

XML_ParserFree(parser);

// close the XML file
fclose(xmlfile);

getch();
return 0;
}
-- end of C file

Peter
 
S

SM Ryan

(e-mail address removed) (Maarten Verhage) wrote:
# Hi All,
#
# I've made a modified version of the Expat elements.c example. What I
# want the program to do is to recognize a hardcoded
# element-name/tag-name and then execute some code which has access to
# the data(e.g. "Maarten Verhage" in XML file).
#
# The current situation (problem) is:
#
# 1. The XML parser calls the function startElement when it finds a tag,
# in this function I don't have access to the data between the tags.
#
# 2. The XML parser calls the function charHandler when it finds data,
# in this function I don't have access to the tag-name.

# int *depthPtr = userData;

Instead if just an integer, set the user data to a structure, and pass
information among the callbacks with this structure.
http://www.rawbw.com/~wyrmwif/html/wyrm-expat.html#16
is an example of the kind of callback structure that can be used.
 
M

Maarten Verhage

Thank you both for your suggestions!

For everybody who had similar problems like me, here is a code sample,
which also looks into the arguments of the elements. There should be a
better way of programming like this, but my C knowledge is limited.

-- start det_tagname.c file
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include "expat.h"

#define XMLFILENAME "master.smil"

typedef struct
{
int found;
char elementName[10];
char attrElementName[3][10];
char attrData[3][20];
int numberAttr;
} S_MY_DATA,*PS_MY_DATA;

static void XMLCALL startElement(void *userData, const char *name,
const char **atts)
{
int word = 0;
//int character = 0;
PS_MY_DATA pMy = userData;

// compare the name and set found to 1
if (strcmp(name, "ref") == 0)
{
pMy->found = 1;
strcpy(pMy->elementName, name);

while(*atts) // element
{
sprintf(pMy->attrElementName[word],"%s", *atts++);
sprintf(pMy->attrData[word],"%s", *atts++);
word++;
}
pMy->numberAttr = word;
}
}



static void XMLCALL endElement(void *userData, const char *name)
{
}

static void XMLCALL charHandler(void *userData, const XML_Char *s, int
len)
{
int i;
int currentAttr = 0;

PS_MY_DATA pMy = userData;
// if found in pMy is 1 then print
if (pMy->found == 1)
{
fprintf(stdout, "\n\nelementName 0: %s", pMy->elementName);
for (i = 0; i < len; i++)
{
fprintf(stdout, "%c", s);
}

for (currentAttr = 0; currentAttr < pMy->numberAttr; currentAttr++)
{
fprintf(stdout,
"attrElementName %d: %s",
currentAttr,
pMy->attrElementName[currentAttr]);
fprintf(stdout,
"\nattrData %d: %s\n",
currentAttr,
pMy->attrData[currentAttr]);
} // end loop
pMy->found = 0;
}
}

int main(int argc, char *argv[])
{
FILE *xmlfile;
char buf[BUFSIZ];
PS_MY_DATA pMyData;
XML_Parser parser = XML_ParserCreate(NULL);

int done;

pMyData = malloc(sizeof(S_MY_DATA));
pMyData->found = 0;
pMyData->numberAttr = 0;

XML_SetUserData(parser, pMyData);
XML_SetElementHandler(parser, startElement, endElement);
XML_SetCharacterDataHandler(parser, charHandler);

// open XML file
if ((xmlfile = fopen(XMLFILENAME, "r")) == NULL)
{
fprintf(stderr, "Error opening XML file\n");
getch();
return -1;
}

do
{
size_t len = fread(buf, 1, sizeof(buf), xmlfile);
done = len < sizeof(buf);
if (XML_Parse(parser, buf, len, done) == XML_STATUS_ERROR)
{
fprintf(stderr,
"%s at line %d\n",
XML_ErrorString(XML_GetErrorCode(parser)),
XML_GetCurrentLineNumber(parser));
return 1;
}
} while (!done);

XML_ParserFree(parser);

// close the XML file
fclose(xmlfile);

free(pMyData);

getch();
return 0;
}
-- end det_tagname.c file
 
C

CBFalconer

Maarten said:
Thank you both for your suggestions!

Who, about what? No quotations, no attributions, etc.
For everybody who had similar problems like me, here is a code
sample, which also looks into the arguments of the elements.
There should be a better way of programming like this, but my C
knowledge is limited.

-- start det_tagname.c file
#include <stdio.h>
#include <conio.h>

No such standard include file.
#include <string.h>
#include "expat.h"

This is not shown here.
#define XMLFILENAME "master.smil"

typedef struct
{
int found;
char elementName[10];
char attrElementName[3][10];
char attrData[3][20];
int numberAttr;
} S_MY_DATA,*PS_MY_DATA;

static void XMLCALL startElement(void *userData, const char *name,
^^^^^^^
Undefined type ^^^
const char **atts)
{
int word = 0;
//int character = 0;

Do not use // comments unless you are using C99. Do not use them
in any case in usenet postings.

Your postings on c.l.c should be completely understandable with
only the C standard as auxiliary information.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top