xmlparser.cpp
来自「可移植的xml库。已经在windows和linux上测试通过。只使用C++ Ru」· C++ 代码 · 共 353 行
CPP
353 行
//xmlparser.cpp
#include "xml.h"
CXMLParser::CXMLParser()
{
init();
}
CXMLParser::~CXMLParser()
{
reset();
}
void CXMLParser::init()
{
m_x = 0;
m_c = 0;
m_ln = 0;
m_last = 0;
m_navi = 0;
m_char = 0;
m_depth = 0;
m_ecode = 0;
m_naviexp = 0;
m_stopLevel = 0;
m_flags = F_SAX;
m_chunkLevel = 0;
m_bufsize = 4096;
memset(m_estr,0,sizeof(m_estr));
}
void CXMLParser::reset()
{
if(m_last) m_last->free();
m_pb.clear();
init();
}
CXMLNode* CXMLParser::clearTree()
{
CXMLNode *p = m_last;
m_last = 0;
if(p)
{
if(p->getParent() && !m_ecode) setupErrCtx(p->getParent()->getNod(),E_XML_NO_CLOSE);
CXMLNode *x;
for(;(x=p->getParent())!=0;p=x);
for(;(x=p->getPrev())!=0;p=x);
}
return p;
}
bool CXMLParser::isClosedOn(const CXMLNode *x)
{
assert(x);
if(!m_last)
{
if((m_flags & F_SAX)
&& (x->getType()==XNT_META
|| x->getFlags(XNF_INDEP_TAG|XNF_CLOSE_TAG)))
{
return true;
}
assert((m_flags & F_SAX) || !x->getFlags(XNF_CLOSE_TAG) && x->getType()==XNT_TAG);
return false;
}
if(!m_last->getFlags(XNF_FULL_NODE)
&& m_last->getType()==XNT_TAG
&& !m_last->getFlags(XNF_INDEP_TAG)
&& m_last->isNodOfExact(x->getNod(),x->getLen()))
{
return true;
}
CXMLNode *p = m_last->getParent();
if(!p) return false;
if(!p->getFlags(XNF_FULL_NODE)
&& p->getType()==XNT_TAG
&& !p->getFlags(XNF_INDEP_TAG)
&& p->isNodOfExact(x->getNod(),x->getLen()))
{
m_last = p;
return true;
}
return false;
}
int CXMLParser::saxParse(CXMLClient *c,FILE *fp)
{
m_c = c;
size_t n;
int e = 0;
assert(m_bufsize);
char *buf = new char[m_bufsize];
for(;;)
{
n = fread(buf,1,m_bufsize,fp);
if(ferror(fp)){delete []buf;return E_XML_LOAD_READ;}
if(n)
{
if((e=saxAppend(buf,n))!=0 && e!=E_XML_PARTIAL){delete []buf;return e;}
}
else break;
}
delete []buf;
return 0;
}
int CXMLParser::saxParseFile(CXMLClient *c,const char *path)
{
assert(path);
FILE *fp = fopen(path,"r");
if(!fp) return E_XML_LOAD_FILE;
int e = saxParse(c,fp);
fclose(fp);
return e;
}
int CXMLParser::saxParse(CXMLClient *c,const char *buf,unsigned bytes)
{
m_c = c;
return saxAppend(buf,bytes);
}
int CXMLParser::domParse(CXMLNode **root,FILE *fp)
{
m_c = 0;
assert(root);
m_flags &= ~F_SAX;
int e = saxParse(0,fp);
*root = clearTree();
if(!e && m_ecode) e = m_ecode;
return e;
}
int CXMLParser::domParseFile(CXMLNode **root,const char *path)
{
m_c = 0;
assert(root);
m_flags &= ~F_SAX;
int e = saxParseFile((CXMLClient *)0,path);
*root = clearTree();
if(!e && m_ecode) e = m_ecode;
return e;
}
int CXMLParser::domParse(CXMLNode **root,const char *buf,unsigned bytes)
{
m_c = 0;
assert(root);
m_flags &= ~F_SAX;
int e = saxParse(0,buf,bytes);
*root = clearTree();
if(!e && m_ecode) e = m_ecode;
return e;
}
int CXMLParser::setupErrCtx(const char *p,int e)
{
strncpy(m_estr,p,sizeof(m_estr));
m_estr[sizeof(m_estr)-1] = 0;
m_ecode = e;
return e;
}
int CXMLParser::saxAppend(const char *buf,unsigned bytes)
{
assert(buf);
if(!bytes && !(bytes=strlen(buf))) return 0;
int err = 0;
if((err=m_pb.append(buf,bytes))!=0) return err;
m_pb[m_pb.getUsed()] = 0;
const char *t,*b,*e;
const char *p = m_pb;
CXMLNode *x;
char c;
bool ctag;
unsigned type;
b = p;
for(;!err && *p && m_navi!=XPS_STOP;)
{
b = p;
err = CXMLNode::findClosePos(p,&e);
if(!e && !err) break;
for(;b<p;++b,++m_char) if(*b=='\n'){++m_ln;m_char=0;}
if(err) return setupErrCtx(b,err);
if(*b!='<' && !m_depth) return setupErrCtx(b,E_XML_BAD_CDATA);//no C data allowed in root
t = p = b;
if(p[0]=='<' && p[1]=='!' && p[2]=='-' && p[3]=='-')
{
if(!(m_flags & F_LOAD_COMMENT))
{
for(;b<e;++b,++m_char) if(*b=='\n'){++m_ln;m_char=0;}
m_char += 3;
p = e + 3;
continue;
}
}
t = b;
x = CXMLNode::load(&m_xnc,b,e,&err,m_x);
if(err)
{
x->free();
for(;t<b;++t,++m_char) if(*t=='\n'){++m_ln;m_char=0;}
if(err==E_XML_EMPTY_COMMENT) continue;
return setupErrCtx(b,err);
}
if((type=x->getType())==XNT_META || type==XNT_COMMENT || type==XNT_CDATA || x->getFlags(XNF_INDEP_TAG)) x->setDepth(m_depth);
else if(x->getFlags(XNF_CLOSE_TAG)) x->setDepth(m_depth--);
else x->setDepth(m_depth++);
if(t<b)
{
for(;t<b;++t,++m_char) if(*t=='\n'){++m_ln;m_char=0;}
}
ctag = false;
if(type==XNT_META) c = (char)x->getFlags(0xff);
if(m_stopLevel>0 && x->getDepth()>m_stopLevel) x->free();
else if(m_navi && m_naviexp<x->getDepth()) x->free();
else if(x->getDepth()<m_chunkLevel) m_navi = m_c->handleNode(*this,x);
else
{
ctag = ((type!=XNT_META) && x->getFlags(XNF_CLOSE_TAG)) || x->getFlags(XNF_INDEP_TAG)!=0;
if((m_flags & F_SAX) && ctag && m_depth<m_chunkLevel)
{
assert(!m_last);
if(m_last)
{
m_navi = XPS_STOP;
return setupErrCtx(m_last->getNod(),E_XML_NO_CLOSE);
}
m_navi = m_c->handleNode(*this,x);
}
else
{
if(type==XNT_TAG && x->getFlags(XNF_CLOSE_TAG)) m_ecode = appendTermNode(x);
else m_ecode = appendNTNode(x);
if(m_ecode) return setupErrCtx(b,m_ecode);
if((m_flags & F_SAX) && ctag && m_depth==m_chunkLevel) m_navi = m_c->handleNode(*this,clearTree());
}
}
if(m_navi>0)
{
if(m_navi==1 && ctag) --m_navi;
if(m_navi)
{
m_naviexp = m_depth - m_navi;
if(m_naviexp<=0) m_navi = XPS_STOP;
}
}
t = b;
xmlSkipBlanks(b);
for(;t<b;++t,++m_char) if(*t=='\n'){++m_ln;m_char=0;}
if(type==XNT_TAG || type==XNT_META)
{
if(type==XNT_META)
{
assert(b[0]==c);
++b;++m_char;
}
assert(*b=='>' || *b=='/');
if(*b=='/')
{
++b;++m_char;
assert(*b=='>');
}
++b;++m_char;
}
else if(type==XNT_COMMENT)
{
assert(b[0]=='-' && b[1]=='-' && b[2]=='>');
b += 3;
m_char += 3;
}
t = b;
xmlSkipBlanks(b);
for(;t<b;++t,++m_char) if(*t=='\n'){++m_ln;m_char=0;}
if(!*b) break;
p = b;
}
p = b;
if(!err)
{
if(m_depth>0 || *p) err = E_XML_PARTIAL;
else if(m_depth<0) err = E_XML_BAD_TILE;
if(err) setupErrCtx(p,err);
}
m_pb.trimLeft((unsigned)(p-(const char *)m_pb));
m_pb[m_pb.getUsed()] = 0;
return err;
}
int CXMLParser::appendNTNode(CXMLNode *x)
{
if(!m_last)
{
if(!(m_flags & F_SAX) && x->getDepth()!=0){x->free();return E_XML_BAD_TILE;}
else{m_last=x;return 0;}
}
if(x->getDepth()>m_last->getDepth())
{
m_last->appendChild(x);
m_last = x;
return 0;
}
for(;x->getDepth()<m_last->getDepth();m_last=m_last->getParent())
{
if(!m_last->getParent())
{
x->free();
return E_XML_BAD_TILE;
}
}
assert(x->getDepth()==m_last->getDepth());
m_last->appendSibling(x);
m_last = x;
return 0;
}
int CXMLParser::appendTermNode(CXMLNode *x)
{
if(!m_last)
{
if(x->getType()!=XNT_META && (!(m_flags & F_SAX) || (x->getFlags(XNF_CLOSE_TAG))))
{
x->free();
return E_XML_BAD_TILE;
}
else{m_last=x;return 0;}
}
for(;x->getDepth()<=m_last->getDepth();m_last=m_last->getParent())
{
if(!m_last->getParent())
{
x->free();
return E_XML_BAD_TILE;
}
}
if(x->getDepth()-m_last->getDepth()!=1)
{
x->free();
return E_XML_BAD_TILE;
}
if(!isClosedOn(x))
{
x->free();
return E_XML_BAD_CLOSE;
}
m_last->setFlags(XNF_FULL_NODE);
if(!m_last->getChildren()) m_last->setFlags(XNF_INDEP_TAG);
x->free();
return 0;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?