// XML.cpp: implementation of the CXML class.
//
//////////////////////////////////////////////////////////////////////
/*
// History
29 Mar 2001 - Fixed error allowing xml declaration to be read as root element
Fixed several memory leaks.
25 Aug 2000 - renamed helper class from pre XML notation of Param to XML Attribute convention
25 Aug 2000 - Added special funcitons to support standard names of ID and NAME.
20 July 2000 - Add Serialization to class to support embedding in binary applications.
20 July 2000 - Added copy functions
14 July 2000 - Modified read buffer to support large blocks of text and parameter fields.
*/
#include "stdafx.h"
#include "XML.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
// Implementation of the list of child Tagged Blocks
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CAttributeList::CAttributeList()
{
}
CAttributeList::~CAttributeList()
{
CAttribute *d;
while(this->GetCount()>0)
{
d=GetTail();
RemoveTail();
delete d;
}
}
CAttribute::CAttribute()
{
}
CAttribute::~CAttribute()
{
}
CMabString CAttribute::GetAttributeText()
{
return m_AttributeValue;
}
int CAttribute::GetAttributeInt()
{
return m_AttributeValue.GetInt();
}
long CAttribute::GetAttributeLong()
{
return m_AttributeValue.GetLong();
}
float CAttribute::GetAttributeFloat()
{
return m_AttributeValue.GetFloat();
}
double CAttribute::GetAttributeDouble()
{
return m_AttributeValue.GetDouble();
}
void CAttribute::SetAttribute(LPCTSTR Value)
{
m_AttributeValue = Value;
}
void CAttribute::SetAttribute(int Value)
{
CMabString sVal;
sVal.PutInt(Value);
SetAttribute(sVal);
}
void CAttribute::SetAttribute(long Value)
{
CMabString sVal;
sVal.PutLong(Value);
SetAttribute(sVal);
}
void CAttribute::SetAttribute(float Value)
{
CMabString sVal;
sVal.PutFloat(Value);
SetAttribute(sVal);
}
void CAttribute::SetAttribute(double Value)
{
CMabString sVal;
sVal.PutDouble(Value);
SetAttribute(sVal);
}
CMabString CAttribute::GetField(char Delim, int FieldNum)
{
CMabString sf;
sf = m_AttributeValue.GetField(Delim,FieldNum);
return sf;
}
CMabString CAttribute::StepField(char Delim)
{
CMabString sf;
sf = m_AttributeValue.StepField(Delim);
return sf;
}
CMabString CAttribute::NextField(char Delim)
{
CMabString sf;
sf = m_AttributeValue.NextField(Delim);
return sf;
}
int CAttribute::GetFieldCount(char Delim)
{
return m_AttributeValue.GetFieldCount(Delim);
}
CAttribute* CAttribute::Copy()
{
CAttribute* copy;
copy = new CAttribute;
copy->m_AttributeName = m_AttributeName;
copy->m_AttributeValue = m_AttributeValue;
return copy;
}
// Added Serialization to support imbedded application data. 20 July 2000
IMPLEMENT_SERIAL(CAttribute, CObject, 0);
void CAttribute::Serialize(CArchive &ar)
{
if(ar.IsStoring())
{
// ar << m_AttributeName << m_AttributeValue;
}
else
{
// ar >> m_AttributeName >> m_AttributeValue;
}
}
//&&&&&&&&&&&&&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// Implementation of the list of child Tagged Blocks
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CXMLList::CXMLList()
{
}
CXMLList::~CXMLList()
{
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CXML::CXML()
{
m_EOF=FALSE;
m_AttributePos=NULL;
m_ChildPos=NULL;
m_TextBlock="";
m_TagName = "";
m_TextBlock = "";
m_FileName = "";
}
CXML::~CXML()
{
ResetContents();
}
void CXML::AddChild(CXML *Child)
{
if(Child==NULL) return;
if(Child->m_TagName.GetLength()<1)
{
AfxMessageBox("No Valid Tag Name");
}
m_ChildList.AddTail(Child);
}
void CXML::AddAttr(CAttribute *Attribute)
{
POSITION pos;
CMabString NewName = Attribute->m_AttributeName;
CAttribute *OldAttribute;
if(m_AttributeList.GetCount()<1)
{
m_AttributeList.AddHead(Attribute);
return;
}
pos = m_AttributeList.GetHeadPosition();
while(pos!=NULL)
{
OldAttribute = m_AttributeList.GetAt(pos);
if(NewName.CompareNoCase(OldAttribute->m_AttributeName)==0)
{
OldAttribute->m_AttributeValue = Attribute->m_AttributeValue;
delete Attribute;
return;
}
else if(NewName<=OldAttribute->m_AttributeName)
{
m_AttributeList.InsertBefore(pos,Attribute);
return;
}
m_AttributeList.GetNext(pos);
}
m_AttributeList.AddTail(Attribute);
return;
}
void CXML::AddToText(CString Text)
{
m_TextBlock+=Text;
}
// Added Copy ability to support versioning - 20 July 2000
CXML* CXML::Copy()
{
CXML* copy;
copy = new CXML;
copy->m_FileName = m_FileName;
copy->m_TagName = m_TagName;
copy->m_TextBlock = m_TextBlock;
CAttribute *p,*np;
p = GetFirstAttribute();
while(p!=NULL)
{
np=p->Copy();
copy->m_AttributeList.AddTail(np);
p = GetNextAttribute();
}
CXML *x,*nx;
x = GetFirstChild();
while(x!=NULL)
{
nx = x->Copy();
copy->m_ChildList.AddTail(nx);
x=GetNextChild();
}
return copy;
}
CXML* CXML::GetChildAt(int index)
{
m_ChildPos = m_ChildList.FindIndex(index);
if(m_ChildPos==NULL) return NULL;
return m_ChildList.GetAt(m_ChildPos);
}
long CXML::GetChildCount()
{
return m_ChildList.GetCount();
}
CXML* CXML::GetCurrentChild()
{
if(m_ChildPos==NULL) return NULL;
return m_ChildList.GetAt(m_ChildPos);
}
CAttribute* CXML::GetCurrentAttribute()
{
if(m_AttributePos==NULL) return NULL;
return m_AttributeList.GetAt(m_AttributePos);
}
CMabString CXML::GetField(char Delim, int FieldNum)
{
CMabString sf;
sf = m_TextBlock.GetField(Delim,FieldNum);
return sf;
}
int CXML::GetFieldCount(char Delim)
{
return m_TextBlock.GetFieldCount(Delim);
}
// 14 July 2000 - Modified line buffer to enhance larger blocks of data.
CMabString CXML::GetNextLine(CFile* pFile)
{
CMabString Line="";
CString ReadLine;
LPSTR LineBuffer;
long NRead,pos1,pos2,pos3,TestChar;
DWORD fpos;
unsigned char lastchar = ' ';
BOOL isEOF=FALSE;
BOOL InQuote=FALSE;
//
// We are inside of the XML block
// we first need to find the next block to handle.
// If there is text data we need to append it to the text data buffer.
// for this element
while(!isEOF && lastchar!='<')
{
fpos = pFile->GetPosition();
ReadLine.Empty();
LineBuffer = ReadLine.GetBuffer(1000);
NRead = pFile->Read(LineBuffer,sizeof(char)*1000);
ReadLine.ReleaseBuffer();
if(NRead<1)
{
m_EOF=TRUE;
return Line;
}
pos1 = ReadLine.Find('<',0);
pos2 = ReadLine.Find('"',0);
pos3 = ReadLine.Find('>',0);
if(InQuote)
{
if(pos2>=0)
{
m_TextBlock+= ReadLine.Left(pos2+1);
pFile->Seek(fpos+pos2+1,CFile::begin);
InQuote=FALSE;
}
m_TextBlock+=ReadLine;
}
else
{
TestChar = ReadLine.GetAt(0);
if(pos1==0)
{
lastchar='<';
pFile->Seek(fpos+1,CFile::begin);
}
else if(pos1==1 && TestChar<33)
{
if(pos3<pos2 && pos3>2)
{
pFile->Seek(fpos+pos3+1,CFile::begin);
Line = ReadLine.Mid(pos1,pos3);
return Line;
}
lastchar='<';
pFile->Seek(fpos+2,CFile::begin);
}
else if(pos2==0)
{
InQuote=TRUE;
m_TextBlock+='"';
pFile->Seek(fpos+1,CFile::begin);
}
else if(pos2>=0 && (pos2<pos1 || pos1<0) )
{
m_TextBlock+= ReadLine.Left(pos2+1);
pFile->Seek(fpos+pos2+1,CFile::begin);
InQuote=TRUE;
}
else if(pos1>=0)
{
m_TextBlock+= ReadLine.Left(pos1);
pFile->Seek(fpos+pos1,CFile::begin);
}
else
{
if(TestChar==10)
m_TextBlock+= ReadLine.Right(ReadLine.GetLength()-1);
else
m_TextBlock+= ReadLine;
}
}
}
// We are now inside of the block to read.
// find the end.
Line ="<";
int InQuote2=1;
while(!isEOF)
{
fpos = pFile->GetPosition();
ReadLine.Empty();
LineBuffer = ReadLine.GetBuffer(1000);
NRead = pFile->Read(LineBuffer,sizeof(char)*1000);
ReadLine.ReleaseBuffer();
if(NRead<1)
{
m_EOF=TRUE;
return Line;
}
pos1 = ReadLine.Find('<',0);
pos2 = ReadLine.Find('"',0);
pos3 = ReadLine.Find('>',0);
if(InQuote2<0)
{
if(pos2<0)
{
Line+=ReadLine;
}
else
{
InQuote2*=-1;
Line+=ReadLine.Left(pos2+1);
pFile->Seek(fpos+pos2+1,CFile::begin);
}
}
else
{
if(pos2>-1 && pos3>-1)
{
if(pos3<pos2)
{
Line+=ReadLine.Left(pos3+1);
pFile->Seek(fpos+pos3+1,CFile::begin);
return Line;
}
InQuote2*=-1;
Line+=ReadLine.Left(pos2+1);
pFile->Seek(fpos+pos2+1,CFile::begin);
}
else if(pos3>-1)
{
Line+=ReadLine.Left(pos3+1);
pFile->Seek(fpos+pos3+1,CFile::begin);
return Line;
}
else if(pos2>-1)
{
InQuote2*=-1;
Line+=ReadLine.Left(pos2+1);
pFile->Seek(fpos+pos2+1,CFile::begin);
}
else
{
Line+=ReadLine;
}
}
}
if(isEOF)
m_EOF=TRUE;
else
Line+=">";
return Line;
}
// Attributeeter functions
CMabString CXML::GetAttrText(LPCTSTR Name)
{
CMabString TestName = Name;
POSITION pos;
CAttribute *Attribute;
if(m_AttributeList.GetCount()<1) return "";
pos = m_AttributeList.GetHeadPosition();
while(pos!=NULL)
{
Attribute = m_AttributeList.GetNext(pos);
if(TestName==Attribute->m_AttributeName)
{
TestName = Attribute->m_AttributeValue;
return TestName;
}
}
TestName="";
return TestName;
}
CMabString CXML::GetAttrTextUS(LPCTSTR Name)
{
CMabString TestName = Name;
POSITION pos;
CAttribute *Attribute;
if(m_AttributeList.GetCount()<1) return "";
pos = m_AttributeList.GetHeadPosition();
while(pos!=NULL)
{
Attribute = m_AttributeList.GetNext(pos);
if(TestName==Attribute->m_AttributeName)
{
TestName = Attribute->m_AttributeValue;
if(TestName.GetLength()<1) TestName="0.00";
return TestName;
}
}
TestName="0.00";
return TestName;
}
int CXML::GetAttrInt(LPCTSTR Name)
{
CMabString sVal = GetAttrText(Name);
return sVal.GetInt();
}
long CXML::GetAttrLong(LPCTSTR Name)
{
CMabString sVal = GetAttrText(Name);
return sVal.GetLong();
}
float CXML::GetAttrFloat(LPCTSTR Name)
{
CMabString sVal = GetAttrText(Name);
return sVal.GetFloat();
}
double CXML::GetAttrDouble(LPCTSTR Name)
{
CMabString sVal = GetAttrText(Name);
return sVal.GetDouble();
}
CAttribute* CXML::GetFirstAttribute()
{
if(m_AttributeList.GetCount()<1)
{
m_AttributePos=NULL;
return NULL;
}
m_AttributePos = m_AttributeList.GetHeadPosition();
return m_AttributeList.GetAt(m_AttributePos);
}
CAttribute* CXML::GetNextAttribute()
{
if(m_AttributePos==NULL) return NULL;
m_AttributeList.GetNext(m_AttributePos);
if(m_AttributePos==NULL) return NULL;
return m_AttributeList.GetAt(m_AttributePos);
}
CAttribute* CXML::GetPrevAttribute()
{
if(m_AttributePos==NULL) return NULL;
m_AttributeList.GetPrev(m_AttributePos);
if(m_AttributePos==NULL) return NULL;
return m_AttributeList.GetAt(m_AttributePos);
}
CAttribute* CXML::GetLastAttribute()
{
if(m_AttributeList.GetCount()<1)
{
m_AttributePos=NULL;
return NULL;
}
m_AttributePos = m_AttributeList.GetTailPosition();
return m_AttributeList.GetAt(m_AttributePos);
}
void CXML::SetCurrentAttr(CAttribute *Attribute)
{
if(m_AttributePos==NULL) return;
m_AttributeList.SetAt(m_AttributePos,Attribute);
}
BOOL CXML::IsStartBlock(CMabString Line, CMabString TagName)
{
int endpos;
if(Line[0]!=60) return FALSE;
if(TagName.GetLength()<1) return TRUE;
endpos = Line.Find(' ');
CMabString LineName;
if(endpos<0)
{
endpos = Line.GetLength();
if(Line[endpos-1]!='>') return FALSE;
if(Line[endpos-2]=='/') endpos--;
LineName = Line.Mid(1,endpos-2);
}
else
LineName = Line.Mid(1,endpos-1);
if(LineName!=TagName) return FALSE;
return TRUE;
}
void CXML::ParseBlock(CMabString Line, CFile *pFile)
{
int LinePos,EndPos;
ResetContents();
// m_ChildList.RemoveAll();
// m_AttributeList.RemoveAll();
if(Line.GetLength()<1) Line=" ";//return;// mab 12 May 2000
if(Line[0]!=60) return;
LinePos = Line.Find(' ');
if(LinePos<0)
{
LinePos = Line.GetLength()-1;
}
m_TagName = Line.Mid(1,LinePos-1);
if(m_TagName[0]=='/') AfxMessageBox("Warning Element Terminator exists without matching initial Block "+m_TagName);
EndPos = Line.GetLength();
if(Line[EndPos-1]!='>') AfxMessageBox("Warning Tag Block is Incomplete");
Line.SetAt(EndPos-1,' ');
BOOL Children=TRUE;
if(Line[EndPos-2]=='/')
{
Children=FALSE;
Line.SetAt(EndPos-2,' ');
}
Line = Line.Right(Line.GetLength() - m_TagName.GetLength()-1);
Line.Trim();
CMabString pname,pval;
while(Line.GetLength()>1)
{
LinePos = Line.Find('=');
if(LinePos<1) break;
pname = Line.Left(LinePos);
pname.Trim();
LinePos = Line.Find('"');
Line = Line.Right(Line.GetLength()-LinePos-1);
LinePos = Line.Find('"');
pval = Line.Left(LinePos);
SetAttr((LPCTSTR)pname,(LPCTSTR)pval);
Line = Line.Right(Line.GetLength()-LinePos-1);
Line.TrimLeft();
}
if(!Children) return;
Line.Empty();
Line = GetNextLine(pFile);
CMabString LastLine;
LastLine = "</";
LastLine += m_TagName;
LastLine += '>';
CXML *child;
while(Line!=LastLine && !m_EOF)
{
if(Line[1]!='!' && Line[1]!='?')
{
child = new CXML;
child->ParseBlock(Line,pFile);
if(child->m_TagName.GetLength()>1) AddChild(child);
else delete child;
}
Line = GetNextLine(pFile);
}
// Test TextBlock for extra line feed.
int TestChar,lenpos;
lenpos = m_TextBlock.GetLength()-1;
if(lenpos>=0)
{
TestChar = m_TextBlock.GetAt(lenpos);
if(TestChar==10) m_TextBlock.SetAt(lenpos,(char)32);
}
}
void CXML::RemoveCurrentAttr()
{
if(m_AttributePos==NULL) return;
CAttribute *Attr;
POSITION pos = m_AttributePos;
Attr = m_AttributeList.GetAt(m_AttributePos);
m_AttributeList.GetNext(pos);
if(pos==NULL)
{
m_AttributeList.RemoveAt(m_AttributePos);
GetLastAttribute();
}
else
{
m_AttributeList.RemoveAt(m_AttributePos);
m_AttributePos = pos;
}
if(Attr!=NULL) delete Attr; // mab 23 mar 2001
}
void CXML::SetAttr(LPCTSTR Name, LPCTSTR Value)
{
POSITION pos;
CMabString NewName = Name;
CAttribute *Attribute,*OldAttribute;
Attribute = new CAttribute;
Attribute->m_AttributeName = Name;
Attribute->m_AttributeValue = Value;
if(m_AttributeList.GetCount()<1)
{
m_AttributeList.AddHead(Attribute);
return;
}
pos = m_AttributeList.GetHeadPosition();
while(pos!=NULL)
{
OldAttribute = m_AttributeList.GetAt(pos);
if(NewName==OldAttribute->m_AttributeName)
{
OldAttribute->m_AttributeValue = Value;
delete Attribute;
return;
}
else if(NewName<=OldAttribute->m_AttributeName)
{
m_AttributeList.InsertBefore(pos,Attribute);
return;
}
m_AttributeList.GetNext(pos);
}
m_AttributeList.AddTail(Attribute);
return;
}
void CXML::SetAttr(LPCTSTR Name, int Value)
{
CMabString sVal;
sVal.PutInt(Value);
SetAttr(Name,sVal);
}
void CXML::SetAttr(LPCTSTR Name, long Value)
{
CMabString sVal;
sVal.PutLong(Value);
SetAttr(Name,sVal);
}
void CXML::SetAttr(LPCTSTR Name, float Value)
{
CMabString sVal;
sVal.PutFloat(Value);
SetAttr(Name,sVal);
}
void CXML::SetAttr(LPCTSTR Name, double Value)
{
CMabString sVal;
sVal.PutDouble(Value);
SetAttr(Name,sVal);
}
// Child functions
CXML* CXML::GetFirstChild()
{
if(m_ChildList.GetCount()<1)
{
m_ChildPos=NULL;
return NULL;
}
m_ChildPos = m_ChildList.GetHeadPosition();
if(m_ChildPos==NULL) return NULL;
return m_ChildList.GetAt(m_ChildPos);
}
CXML* CXML::GetNextChild()
{
if(m_ChildPos==NULL) return NULL;
m_ChildList.GetNext(m_ChildPos);
if(m_ChildPos==NULL) return NULL;
return m_ChildList.GetAt(m_ChildPos);
}
CXML* CXML::GetPrevChild()
{
if(m_ChildPos==NULL) return NULL;
m_ChildList.GetPrev(m_ChildPos);
if(m_ChildPos==NULL) return NULL;
return m_ChildList.GetAt(m_ChildPos);
}
CXML* CXML::GetLastChild()
{
if(m_ChildList.GetCount()<1)
{
m_ChildPos=NULL;
return NULL;
}
m_ChildPos = m_ChildList.GetTailPosition();
return m_ChildList.GetAt(m_ChildPos);
}
void CXML::SetCurrentChild(CXML *Child)
{
if(m_ChildPos==NULL) return;
m_ChildList.SetAt(m_ChildPos,Child);
}
void CXML::RemoveCurrentChild()
{
if(m_ChildPos==NULL) return;
CXML *x;
x = m_ChildList.GetAt(m_ChildPos);
POSITION pos = m_ChildPos;
m_ChildList.GetNext(pos);
if(pos==NULL)
{
m_ChildList.RemoveAt(m_ChildPos);
GetLastChild();
}
else
{
m_ChildList.RemoveAt(m_ChildPos);
m_ChildPos = pos;
}
delete x;
}
void CXML::ResetContents()
{
CAttribute *p;
while(m_AttributeList.GetCount()>0)
{
p=m_AttributeList.GetTail();
m_AttributeList.RemoveTail();
delete p;
}
CXML *x;
while(m_ChildList.GetCount()>0)
{
x=m_ChildList.GetTail();
m_ChildList.RemoveTail();
delete x;
}
m_TextBlock.Empty();
}
long CXML::GetAttrCount()
{
return m_AttributeList.GetCount();
}
void CXML::XMLWrite(CFile *pFile)
{
CMabString Line;
CMabString Addition;
Line = "<";
Line += m_TagName;
CAttribute *Attribute;
Attribute = GetFirstAttribute();
while(Attribute!=NULL)
{
Addition = " ";
Addition += Attribute->m_AttributeName;
Addition += "=\"";
Attribute->m_AttributeValue.Trim();
Addition += Attribute->m_AttributeValue;
Addition += "\"";
Line += Addition;
Attribute = GetNextAttribute();
}
if((m_ChildList.GetCount()<1) && (m_TextBlock.GetLength()<1))
{
Addition = "/>\n";
Line += Addition;
pFile->Write(Line,Line.GetLength());
return;
}
Addition = ">\n";
Line += Addition;
pFile->Write(Line,Line.GetLength());
// Now the children
if(m_TextBlock.GetLength()>0)
{
m_TextBlock+='\n';
pFile->Write(m_TextBlock,m_TextBlock.GetLength());
m_TextBlock = m_TextBlock.Left(m_TextBlock.GetLength()-1);
}
CXML *child;
child = GetFirstChild();
while(child!=NULL)
{
child->XMLWrite(pFile);
child = GetNextChild();
}
// and the terminator
Line = "</";
Line += m_TagName;
Line += ">\n";
pFile->Write(Line,Line.GetLength());
return;
}
BOOL CXML::Open(LPCTSTR InFilter, LPCTSTR TagName)
{
CFile in;
CMabString defext;
CMabString filter = InFilter;
int pos1 = filter.Find('(');
int pos2 = filter.Find(')');
defext = filter.Mid(pos1+1,pos2-pos1-1);
CFileDialog myfile(TRUE,NULL,defext,NULL,filter,NULL);
if(myfile.DoModal()==IDOK)
{
in.Open(myfile.GetPathName(),CFile::modeRead);
XMLRead(&in,TagName);
in.Close();
m_FileName = myfile.GetPathName();
return TRUE;
}
return FALSE;
}
BOOL CXML::SaveAs(LPCTSTR InFilter)
{
CFile in;
CMabString defext;
CMabString filter = InFilter;
int pos1 = filter.Find('(');
int pos2 = filter.Find(')');
defext = filter.Mid(pos1+1,pos2-pos1-1);
CFileDialog myfile(FALSE,NULL,defext,NULL,filter,NULL);
if(myfile.DoModal()==IDOK)
{
in.Open(myfile.GetPathName(),CFile::modeCreate|CFile::modeWrite);
XMLWrite(&in);
in.Close();
m_FileName = myfile.GetPathName();
return TRUE;
}
m_FileName = "";
return FALSE;
}
BOOL CXML::Save(LPCTSTR InFilter)
{
if(m_FileName.GetLength()<1)
{
return SaveAs(InFilter);
}
CFile in;
in.Open(m_FileName,CFile::modeCreate|CFile::modeWrite);
XMLWrite(&in);
in.Close();
return TRUE;
}
void CXML::SetTagName(LPCTSTR NewName)
{
// CString line;
// line.Format("Setting tag from %s to %s",(LPCTSTR)m_TagName,NewName);
// AfxMessageBox(line);
m_TagName = NewName;
}
LPCTSTR CXML::GetTagName()
{
return (LPCTSTR)m_TagName;
}
CMabString CAttribute::GetAttributeName()
{
return m_AttributeName;
}
void CXML::SetText(LPCTSTR NewText)
{
m_TextBlock = NewText;
}
LPCTSTR CXML::GetText()
{
return (LPCTSTR)m_TextBlock;
}
void CXML::InsertChild(CXML *Child)
{
if(m_ChildPos==NULL)
m_ChildList.AddTail(Child);
else
m_ChildList.InsertBefore(m_ChildPos,Child);
return;
}
CMabString CXML::GetTag()
{
return m_TagName;
}
CMabString CXML::GetAttr(LPCTSTR Name)
{
CMabString TestName = Name;
POSITION pos;
CAttribute *Attribute;
if( (m_AttributeList.GetCount()) < 1) return "";
pos = m_AttributeList.GetHeadPosition();
while(pos!=NULL)
{
Attribute = m_AttributeList.GetNext(pos);
if(TestName==Attribute->m_AttributeName) return Attribute->m_AttributeValue;
}
return "";
}
void CXML::SetAttrUS(LPCSTR Name, double value)
{
CString str;
str.Format("%.2f",value+0.001);
SetAttr(Name,str);
}
void CXML::RemoveAttr(LPCSTR Name)
{
CMabString TestName = Name;
CAttribute *Attribute;
if( (m_AttributeList.GetCount()) < 1) return;
Attribute = GetFirstAttribute();
while(Attribute!=NULL)
{
if(TestName==Attribute->m_AttributeName)
{
RemoveCurrentAttr();
return;
}
Attribute = GetNextAttribute();
}
}
BOOL CXML::IsAlpha(char c)
{
if(c>64 && c<91) return TRUE;
if(c>96 && c<123) return TRUE;
return FALSE;
}
CMabString CXML::StepField(char Delim)
{
CMabString sf;
sf = m_TextBlock.StepField(Delim);
return sf;
}
CMabString CXML::FirstField(char Delim)
{
CMabString sf;
sf = m_TextBlock.FirstField(Delim);
return sf;
}
CMabString CXML::NextField(char Delim)
{
CMabString sf;
sf = m_TextBlock.NextField(Delim);
return sf;
}
BOOL CXML::XMLRead(CFile *pFile, LPCTSTR TagName)
{
m_TagName = TagName;
CMabString NextLine;
NextLine = GetNextLine(pFile);
// Skip header
while(NextLine[1]==63) NextLine=GetNextLine(pFile);
while (!m_EOF && !IsStartBlock(NextLine,TagName))
{
NextLine = GetNextLine(pFile);
}
m_TextBlock.Empty();
if(m_EOF) return FALSE;
else ParseBlock(NextLine,pFile);
return TRUE;
}
CAttribute* CXML::GetAttributePointer(LPCTSTR Name)
{
CMabString TestName = Name;
POSITION pos;
CAttribute *Attribute;
if( (m_AttributeList.GetCount()) < 1) return NULL;
pos = m_AttributeList.GetHeadPosition();
while(pos!=NULL)
{
Attribute = m_AttributeList.GetNext(pos);
if(TestName==Attribute->m_AttributeName) return Attribute;
}
return NULL;
}
IMPLEMENT_SERIAL(CXML, CObject, 0);
void CXML::Serialize(CArchive &ar)
{
if(ar.IsStoring())
{
// ar << m_TagName << m_TextBlock;
}
else
{
// ar >> m_TagName >> m_TextBlock;
}
m_AttributeList.Serialize(ar);
m_ChildList.Serialize(ar);
}
CXML* CXML::RemoveAt(int position)
{
CXML* child;
child = GetChildAt(position);
if(child!=NULL) RemoveCurrentChild();
return child;
}
void CXML::InsertChildBefore(int ZeroBasedPos, CXML *Child)
{
m_ChildList.InsertBefore(m_ChildList.FindIndex(ZeroBasedPos),Child);
}
void CAttribute::AddToText(CString text)
{
m_AttributeValue+=text;
}
// Added 25 Aug 2000 to handle the special case of the ID and Name attributes
CXML* CXML::FindByID(long id)
{
CXML *child,*grand;
child=GetFirstChild();
while(child!=NULL)
{
if(child->GetAttrLong("ID")==id) return child;
grand=child->FindByID(id);
if(grand!=NULL) return grand;
child=GetNextChild();
}
// AfxMessageBox("XML ID NOT FOUND");
return child;
}
CXML* CXML::FindByName(CString name)
{
CXML *child,*grand;
child=GetFirstChild();
while(child!=NULL)
{
if(name.CompareNoCase(child->GetAttrText("NAME"))==0) return child;
grand=child->FindByName(name);
if(grand!=NULL) return grand;
child=GetNextChild();
}
return child;
}
void CXML::SortByName()
{
CXML *c1,*c2;
CString n1;
restart:
c1=GetFirstChild();
c2=GetNextChild();
while(c2!=NULL)
{
n1=c1->GetAttrText("NAME");
if(n1.CompareNoCase(c2->GetAttrText("NAME"))>0)
{
RemoveCurrentChild();
AddChildByName(c2);
goto restart;
};
c1=c2;
c2=GetNextChild();
}
return;
}
void CXML::SortById()
{
CXML *c1,*c2;
long n1;
restart:
c1=GetFirstChild();
c2=GetNextChild();
while(c2!=NULL)
{
n1=c1->GetAttrLong("ID");
if(n1>c2->GetAttrLong("ID"))
{
RemoveCurrentChild();
AddChildById(c2);
goto restart;
};
c1=c2;
c2=GetNextChild();
}
return;
}
void CXML::AddChildByName(CXML *newchild)
{
CXML *child;
CString n1;
child=GetFirstChild();
while(child!=NULL)
{
n1=child->GetAttrText("NAME");
if(n1.CompareNoCase(newchild->GetAttrText("NAME"))>0)
{
InsertChild(newchild);
return;
}
child=GetNextChild();
}
AddChild(newchild);
return;
}
void CXML::AddChildById(CXML *newchild)
{
CXML *child;
long id;
id=newchild->GetAttrLong("ID");
child=GetFirstChild();
while(child!=NULL)
{
if(id<child->GetAttrLong("ID"))
{
InsertChild(newchild);
return;
}
child=GetNextChild();
}
AddChild(newchild);
return;
}