Hi,
iīm trying to build a xml - parser, which should simply list all used
tokens an dattributes including their values. So far, so good, this
works, but now i try to check for illegal phrases in the source
document regarding starttags. here is my parser so far:
tokenlibrary.cpp:
#include <iostream>
using namespace std;
#include <fstream>
#include <string>
#include "token7.h"
ClToken::ClToken()
{
*tokenName='\0';
tokenChild=NULL;
tokenSibling=NULL;
tokenInhalt=new char[1];
*tokenInhalt='\0';
}
int ClToken::getToken(
ifstream &datei, int ebene)
{
int zaehler;
enum zustand zustand;
char zeichen;
char puffer[100];
ClToken *child;
cleanToken();
for (zaehler=0;;)
{
datei.get(zeichen);
if (datei.eof())
{
if (*tokenName == '\0' && tokenChild == NULL && tokenInhalt ==
NULL)
return fillToken(0);
return fillToken(1);
}
switch(zeichen)
{
case '<':
datei.get(zeichen);
if (zeichen=='/')
{
zustand = istEndTag;
if (zaehler!=0)
{
puffer[zaehler]='\0';
tokenInhalt = new char[zaehler+1];
strcpy(tokenInhalt,puffer);
}
}
else
{
datei.putback(zeichen);
if (*tokenName!='\0')
{
datei.putback('<');
if (tokenChild==NULL)
{
ebene++;
tokenChild=new ClToken;
tokenChild->getToken(datei,ebene);
}
else
{
for (child=tokenChild;;child=child->tokenSibling)
{
if (child->tokenSibling==NULL)
{
child->tokenSibling=new ClToken;
//child->tokenSibling->ebene = ebene;
child->tokenSibling->getToken(datei, ebene);
break;
}
}
}
}
else zustand=istStartTag;
}
zaehler=0;
break;
case '>':
puffer[zaehler]='\0';
if (zustand==istEndTag)
{
//cout << "Ausgabe Ebene in getToken: " << this->ebene << "+" <<
this->tokenName << endl;
strcpy(endtagName, puffer);
checkEndtag();
return fillToken(1);
}
if (zustand==istStartTag)
{
att.getAttList(puffer);
//cout <<"TokenName in der Abfrage: " << this->tokenName <<
endl;
strcpy(tokenName,puffer);
checkStarttag();
//cout << "tokenname in switch: " << tokenName<<endl;
}
zaehler=0;
break;
case '\n':
break;
default:
puffer[zaehler]=zeichen;
zaehler++;
break;
}
}
}
int ClToken::fillToken(
int mode)
{
if (*tokenName=='\0')
strcpy(tokenName,"Unbekanntes Element");
if (tokenInhalt==NULL)
{
tokenInhalt=new char[1];
*tokenInhalt='\0';
}
return mode;
}
void ClToken::cleanToken(void)
{
*tokenName='\0';
if (tokenChild!=NULL)
{
delete tokenChild;
tokenChild=NULL;
}
if (tokenInhalt!=NULL)
{
delete tokenInhalt;
tokenInhalt=NULL;
}
}
void ClToken::druckeToken(
int level)
{
druckeTokenEbene(level);
cout << "Token: " << name() << " - " << inhalt() << endl;
if (att.zahlAtt() > 0)
{
for (int i=0;i<att.zahlAtt();i++)
{
druckeTokenEbene(level);
cout << "Attribut " << att.zeigeAttName(i) << " hat den Wert "
<< att.zeigeAttWert(i) << endl;
}
}
if (tokenChild!=NULL) tokenChild->druckeToken(level+1);
if (tokenSibling!=NULL) tokenSibling->druckeToken(level);
}
void ClToken::druckeTokenEbene(
int level)
{
while (level > 0)
{
cout << "| ";
level = level - 1;
}
}
void ClToken::checkEndtag()
{
if ( *tokenName != *endtagName)
{
cout << "fehlendes Endtag: " << tokenName << endl;
}
}
int ClToken::Init(ifstream &datei)
{
ebene = 1;
//cout << "tokenadresse in init: " << &token << endl;
return getToken(datei, ebene);
}
void ClToken::checkStarttag()
{
}
the header for this library:
#include "att.h"
class ClToken
{
public:
ClToken();
char *name() { return tokenName; }
ClToken *child() { return tokenChild; }
char *inhalt() { return tokenInhalt; }
void druckeToken(int ebene);
int getToken(ifstream &datei, int ebene);
ClattToken att;
int Init(ifstream &datei);
private:
void cleanToken();
void druckeTokenEbene(int ebene);
int fillToken(int mode);
char tokenName[64];
char endtagName[64];
ClToken *tokenChild;
ClToken *tokenSibling;
ClToken *tokenParent;
void checkEndtag();
void checkStarttag();
char *tokenInhalt;
int ebene;
char starttagName[64];
char *speicheradresse;
} ;
enum zustand { istStartTag, istEndTag } ;
and the main program:
#include <iostream>
using namespace std;
#include <fstream>
#include <string>
#include "token7.h"
int main()
{
ifstream eingabe;
ClToken *token;
char dateiname[50];
string adresse;
cout << "Bitte geben sie den Namen der Datei an, die eingelesen werden
soll!" << endl;
cin >> dateiname;
eingabe.open(dateiname);
token=new ClToken;
;
if (token->Init(eingabe)!=0) token->druckeToken(1);
eingabe.close();
{
/* bitte ignorieren; nur bis zu Ihrer Anmeldung notwendig */
int x;
cin >> x;
}
}
here are also two more files that are necessary to run the program,
but donīt have anything to do with my problem ( at least i hope so );
theyīre used to read the values and names of atrributes:
header:
class ClattToken
{
private:
int anzahlAtt;
char *attName[10];
char *attValue[10];
public:
int getAttList(char *eingabe);
char *zeigeAttName(int id) {return attName[id];}
char *zeigeAttWert(int id) {return attValue[id];}
int zahlAtt() {return anzahlAtt;}
};
and the library for this header:
#include <iostream>
using namespace std;
#include <fstream>
#include <string>
#include "att.h"
int ClattToken::getAttList(
char *eingabe)
{
char puffer[100];
int zaehler;
enum zustand { zwischenTags, inNamen, erwarteAttributNamen,
erwarteAttributWert,
verarbeiteAttributWert} ;
enum zustand zustand;
for (zaehler=0,zustand=inNamen,anzahlAtt=0;*eingabe!=' \0';
eingabe = eingabe + 1)
{
switch(*eingabe)
{
case ' ':
if (zustand == inNamen)
{
zustand = erwarteAttributNamen;
*eingabe='\0';
zaehler=0;
}
else if (zustand == verarbeiteAttributWert)
{
puffer[zaehler] = *eingabe;
zaehler++;
}
break;
case '=':
if (zustand == erwarteAttributNamen)
{
zustand = erwarteAttributWert;
puffer[zaehler] = '\0';
attName[anzahlAtt] = new char[zaehler+1];
strcpy(attName[anzahlAtt],puffer);
zaehler=0;
}
else if (zustand == verarbeiteAttributWert)
{
puffer[zaehler] = *eingabe;
zaehler++;
}
else cout << "Fehlerhaftes Zeichen! '='" << endl;
break;
case '"':
if (zustand == erwarteAttributWert)
{
zustand = verarbeiteAttributWert;
zaehler = 0;
}
else if (zustand == verarbeiteAttributWert)
{
zustand = erwarteAttributNamen;
puffer[zaehler] = '\0';
attValue[anzahlAtt] = new char[zaehler+1];
strcpy(attValue[anzahlAtt],puffer);
zaehler=0;
anzahlAtt++;
}
else cout << "Fehlerhaftes Zeichen! '\"'" << endl;
break;
default:
if (zustand >= erwarteAttributNamen)
{
puffer[zaehler] = *eingabe;
zaehler++;
}
break;
}
}
return 1;
}
when itīs done, the parser should be able to recognize, when a
starttag isnīt allowed, hereīs an exmaple for a file the parser
shouldnīt accept:
<kurs>
<person>
<vorname attr1="value1">Margarita</vorname>
<famname attr1="value1" attr2="value2">weber
</person>
<person>
</kurs>
it should only accept a structure like
<kurs>
<person>
<vorname attr1="value1">Margarita</vorname>
<famname attr1="value1" attr2="value2">weber</famname>
</person>
</kurs>
with no new starttags within the structure, i already tried several
things, but i donīt have any idea how to compare the names of new
starttags with the already existing names of parent - or sibling names
which is necessary for my plan!
can anyone help me? i donīt have any more ideaqs how to solve this
problem!
Thank you,
Patrick Gunia