📄 xml.cpp
字号:
#include "stdafx.h"
#include "xml.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define XML_TOKEN_START 1 // <
#define XML_TOKEN_END 2 // >
#define XML_TOKEN_START2 3 // </
#define XML_TOKEN_END2 4 // />
#define XML_TOKEN_PI_START 5 // <?
#define XML_TOKEN_PI_END 6 // ?>
#define XML_TOKEN_TEXT 7
#define XML_TOKEN_NAME 8
#define XML_TOKEN_STRING 9 // "xxx" or 'xxx'
#define XML_TOKEN_EQUAL 10 // =
#define XML_TOKEN_EOF 11
#define XML_TOKEN_CDATA 12
#define XML_TOKEN_INVALID 13
char *tokenTypeStrings[] =
{
"", //base 0
"<",
">",
"</",
"/>",
"<?",
"?>",
"text",
"tag/attrname",
"string",
"=",
"EOF",
"CDATA",
"invalid",
};
void ASSERT_TOKEN(int x);
static int bReadTag = 0;
static int tokenType = XML_TOKEN_EOF;
static char tokenValue[MAX_TOKEN_LEN+1];
static char textValue[MAX_TEXT_LEN+1];
static char *pCurrent = NULL;
static char *pBuffer = NULL;
static int lineNumber = 0;
static int colNumber = 0;
void strncpyx(char *dest, const char *src, int len)
{
if(src==NULL)
{
dest[0]=0;
return;
}
strncpy(dest, src, len-1);
dest[len-1] = 0;
}
TXMLAttr::TXMLAttr()
{
m_strName[0]=0;
m_strValue=NULL;
brother = NULL;
lineNo = 0;
}
TXMLAttr::~TXMLAttr()
{
if(m_strValue)
delete m_strValue;
}
void TXMLAttr::setName(const char* src)
{
if(strlen(src) >ATTRNAME_LENGTH)
{
strncpy(m_strName,src,ATTRNAME_LENGTH);
m_strName[ATTRNAME_LENGTH]=0;
}
else
{
strcpy(m_strName,src);
}
}
char* TXMLAttr::getName()
{
return m_strName;
}
void TXMLAttr::setValue(const char* src)
{
if(m_strValue)
delete m_strValue;
m_strValue=new char[strlen(src)+1];
strcpy(m_strValue,src);
}
char* TXMLAttr::getValue()
{
return m_strValue;
}
TXMLAttr* TXMLAttr::dup()
{
TXMLAttr* attr=new TXMLAttr;
attr->setName(m_strName);
attr->setValue(m_strValue);
if(brother!=NULL)
attr->brother=brother->dup();
attr->lineNo=lineNo;
return attr;
}
char* TXMLAttr::toStr()
{
char* s=new char[strlen(m_strName) + strlen(m_strValue) + 4];
sprintf(s,"%s=\"%s\"",m_strName,m_strValue);
return s;
}
TXMLElem::TXMLElem()
{
child=NULL;
brother=NULL;
parent=NULL;
attr = NULL;
lineNo = 0;
m_strTag[0]=0;
m_strContent=NULL;
}
TXMLElem::~TXMLElem()
{
TXMLElem* p=child;
while(p!=NULL)
{
TXMLElem *pNext = p->brother;
delete p;
p = pNext;
}
{
TXMLAttr* p=attr;
while(p!=NULL)
{
TXMLAttr *pNext = p->brother;
delete p;
p = pNext;
}
}
if(m_strContent)
{
delete m_strContent;
m_strContent=NULL;
}
}
TXMLElem* TXMLElem::dup(TXMLElem* aParent)
{
TXMLElem* elem=new TXMLElem;
elem->setTag(m_strTag);
elem->setContent(m_strContent);
TXMLElem* pChild=child;
while(pChild!=NULL)
{
TXMLElem* pDupChild=pChild->dup(elem);
elem->addChild(pDupChild);
pChild=pChild->brother;
}
elem->parent=aParent;
if(attr!=NULL)
elem->attr=attr->dup();
elem->lineNo=lineNo;
return elem;
}
void TXMLElem::setTag(const char* src)
{
if(strlen(src) >TAG_LENGTH)
{
strncpy(m_strTag,src,TAG_LENGTH);
m_strTag[TAG_LENGTH]=0;
}
else
{
strcpy(m_strTag,src);
}
}
void TXMLElem::setContent(const char* src)
{
if(m_strContent)
delete m_strContent;
m_strContent = new char[strlen(src)+1];
strcpy(m_strContent,src);
}
char* TXMLElem::getTag()
{
return m_strTag;
}
char* TXMLElem::getContent()
{
return m_strContent;
}
static char *pLast = NULL;
void GetLocation(char *pCurr)
{
char *p = pLast;
while(p != pCurr)
{
if(*p == '\n')
{
lineNumber ++;
colNumber = 1;
}
colNumber ++;
p++;
}
pLast = pCurr;
}
#define TOKEN_HEAD 10
void GetToken()
{
tokenValue[0] = 0;
textValue[0] = 0;
char *p = pCurrent;
if(bReadTag)
{
//skip blank
while(*p==' ' || *p=='\t' || *p=='\n' || *p=='\r')
{
p++;
}
//only handle NAME, STRING, EQUAL, END, END2
GetLocation(p);
if(*p==0)
{
tokenType = XML_TOKEN_EOF;
}
else if(strncmp(p, "/>", 2) == 0)
{
tokenType = XML_TOKEN_END2;
strcpy(tokenValue, "/>");
p+=2;
bReadTag = 0;
}
else if(*p=='>')
{
tokenType = XML_TOKEN_END;
strcpy(tokenValue, ">");
p++;
bReadTag = 0;
}
else if(*p=='=')
{
tokenType = XML_TOKEN_EQUAL;
strcpy(tokenValue, "=");
p++;
}
else if(*p=='"' || *p=='\'')
{
char beginChar=*p;
p++;
char *pBegin = p;
// while(*p !=0 && *p !='\n' && *p != beginChar)
while(*p !=0 && *p != beginChar)
p++;
if( *p != beginChar || p - pBegin+1 > MAX_TOKEN_LEN )
{
//too long string
strncpyx(tokenValue, pBegin, TOKEN_HEAD);
strcat(tokenValue, "(Too long)");
tokenType = XML_TOKEN_INVALID;
}
else
{
tokenType = XML_TOKEN_STRING;
strncpyx(tokenValue, pBegin, p - pBegin+1);
xmlTextDecode(tokenValue);
p++;
}
}
else if(isalpha(*p))
{
char *pBegin = p;
p++;
while(isalpha(*p) || *p>='0' && *p<='9' || *p == '_' || *p == ':'||*p == '-')
{
p++;
}
if(p - pBegin+1 > MAX_TOKEN_LEN )
{
//too long name
strncpyx(tokenValue, pBegin, TOKEN_HEAD);
strcat(tokenValue, "(Too long)");
tokenType = XML_TOKEN_INVALID;
}
else
{
tokenType = XML_TOKEN_NAME;
strncpyx(tokenValue, pBegin, p - pBegin+1);
//luojianmin add on 2004/05/13
char* tok=strchr(tokenValue,':');
if(tok!=NULL && strchr(tok+1,':')!=NULL)
tokenType = XML_TOKEN_INVALID;
}
}
else
{
//unknown token
strncpyx(tokenValue, p, TOKEN_HEAD);
tokenType = XML_TOKEN_INVALID;
}
}
else
{
restart:
//skip blank
while(*p==' ' || *p=='\t' || *p=='\n' || *p=='\r')
{
p++;
}
//only handle BEGIN, COMMENT, CDATA, PI, TEXT
GetLocation(p);
if(*p==0)
{
tokenType = XML_TOKEN_EOF;
}
else if(strncmp(p, "<!--", 4) == 0)
{
char *pTail = strstr(p, "-->");
if(!pTail)
{
//invalid comment
strcpy(tokenValue, "<!-- ... (NEED -->)");
tokenType = XML_TOKEN_INVALID;
}
else
{
p = pTail + 3;
goto restart;
}
}
else if(strncmp(p, "<?", 2) == 0)
{
char *pTail = strstr(p, "?>");
if(!pTail)
{
//invalid Process Instrution
strcpy(tokenValue, "<? ... (NEED ?>)");
tokenType = XML_TOKEN_INVALID;
}
else
{
p = pTail + 2;
goto restart;
}
}
else if(strncmp(p, "<![CDATA[", 9) == 0)
{
char *pTail = strstr(p, "]]>");
if(!pTail)
{
//invalid Process Instrution
strcpy(tokenValue, "<![CDATA ... (NEED ]]>)");
tokenType = XML_TOKEN_INVALID;
}
else
{
//don't check it's length?
if(pTail - (p+9) >MAX_TEXT_LEN)
{
strncpyx(textValue, p, TOKEN_HEAD);
strcat(textValue, "(Too long)");
tokenType = XML_TOKEN_INVALID;
}
else
{
tokenType = XML_TOKEN_CDATA;
strncpyx(textValue, p+9, pTail-(p+9)+1);
p = pTail + 3;
}
}
}
else if(strncmp(p, "</", 2) == 0)
{
tokenType = XML_TOKEN_START2;
strcpy(tokenValue, "</");
p+=2;
bReadTag = 1;
}
else if(*p=='<')
{
tokenType = XML_TOKEN_START;
strcpy(tokenValue, "<");
p++;
bReadTag = 1;
}
else
{
//we think this is a text
char *pBegin = p;
while(*p !=0 && *p !='<')
p++;
if(p - pBegin+1 > MAX_TEXT_LEN )
{
//too long text
strncpyx(textValue, pBegin, TOKEN_HEAD);
strcat(textValue, "(Too long)");
tokenType = XML_TOKEN_INVALID;
}
else
{
tokenType = XML_TOKEN_TEXT;
strncpyx(textValue, pBegin, p - pBegin+1);
xmlTextDecode(textValue);
}
}
}
pCurrent = p;
}
void TXMLElem::addAttr(TXMLAttr* pAttr)
{
if(attr==NULL)
{
attr=pAttr;
return;
}
TXMLAttr* p=attr;
while(p->brother!=NULL)
p=p->brother;
p->brother=pAttr;
}
char* TXMLElem::GetAttrValue(const char *name)
{
TXMLAttr* p=GetAttr(name);
if(p)
{
return p->getValue();
}
else
return NULL;
}
TXMLAttr *TXMLElem::GetAttr(const char *name)
{
for(TXMLAttr* p=attr; p!=NULL; p=p->brother)
{
if(stricmp(name, p->getName()) == 0)
return p;
}
return NULL;
}
int TXMLElem::GetAttrNum()
{
int i=0;
for(TXMLAttr* p=attr; p!=NULL; p=p->brother)
{
i++;
}
return i;
}
TXMLAttr *TXMLElem::GetAttr(int index)
{
int i=0;
for(TXMLAttr* p=attr; p!=NULL; p=p->brother)
{
if(i == index)
return p;
i++;
}
return NULL;
}
TXMLElem *TXMLElem::GetSubElem(const char *tag1)
{
for(TXMLElem* p=child; p!=NULL; p=p->brother)
{
if(stricmp(tag1, p->getTag()) == 0)
return p;
}
return NULL;
}
int TXMLElem::GetSubElemNum()
{
int i=0;
for(TXMLElem* p=child; p!=NULL; p=p->brother)
{
i++;
}
return i;
}
int TXMLElem::GetSubElemNumByTag(char* strTag)
{
if (strTag==NULL) return 0;
int i=0;
for(TXMLElem* p=child; p!=NULL; p=p->brother)
{
if(p->getTag()!=NULL && stricmp(p->getTag(),strTag)==0)
i++;
}
return i;
}
int TXMLElem::GetSubElemName(int index,char* name)
{
TXMLElem* p=GetSubElem(index);
if(p!=NULL)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -