00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "CATXMLParser.h"
00014 #include "CATXMLObject.h"
00015 #include "CATStreamFile.h"
00016 CATXMLParser::CATXMLParser()
00017 {
00018 fCurParent = 0;
00019 }
00020
00021
00022 CATXMLParser::~CATXMLParser()
00023 {
00024 }
00025
00026 CATResult CATXMLParser::Parse(const CATWChar* path,
00027 CATXMLFactory* factory,
00028 CATXMLObject*& root)
00029 {
00030 if (!path)
00031 {
00032 return CAT_ERR_XML_PARSER_INVALID_PATH;
00033 }
00034
00035 CATStreamFile stream;
00036 CATResult result;
00037 if (CATFAILED(result = stream.Open(path,CATStream::READ_ONLY)))
00038 {
00039 return result;
00040 }
00041 result = CATXMLParser::ParseStream(&stream,factory,root);
00042 stream.Close();
00043 return result;
00044 }
00045
00046
00047 CATResult CATXMLParser::ParseStream(CATStream* stream,
00048 CATXMLFactory* factory,
00049 CATXMLObject*& root)
00050 {
00051 CATResult result;
00052 if (!stream)
00053 {
00054 return CATRESULT(CAT_ERR_XML_PARSER_INVALID_PATH);
00055 }
00056
00057 stream->SeekAbsolute(0);
00058 CATInt64 filesize = 0;
00059 stream->Size(filesize);
00060
00061 CATUInt32 fsize = (CATUInt32)filesize;
00062 if ((CATInt64)fsize != filesize)
00063 {
00064 return CATRESULT(CAT_ERR_XML_PARSER_OUT_OF_MEMORY);
00065 }
00066
00067 CATUInt8* buffer = new CATUInt8[fsize+1];
00068 if (!buffer)
00069 {
00070 return CATRESULT(CAT_ERR_XML_PARSER_OUT_OF_MEMORY);
00071 }
00072
00073 memset(buffer,0,fsize+1);
00074 if (CATFAILED(result = stream->Read(buffer,fsize)))
00075 {
00076 delete [] buffer;
00077 return result;
00078 }
00079
00080 result = ParseMemory(buffer,fsize,factory,root);
00081
00082 delete [] buffer;
00083 return result;
00084 }
00085
00086 CATResult CATXMLParser::ParseMemory(const void* memoryBuf,
00087 CATInt32 bufLen,
00088 CATXMLFactory* factory,
00089 CATXMLObject*& root)
00090 {
00091 CATXMLParser* parser = new CATXMLParser();
00092 root = 0;
00093 parser->fRootObjPtr = &root;
00094 parser->fFactory = factory;
00095
00096 XML_Parser expatParser = XML_ParserCreate(0);
00097 XML_SetUserData(expatParser, parser);
00098 XML_SetElementHandler(expatParser,&CATXMLParser::StartElement,&CATXMLParser::EndElement);
00099 XML_SetCharacterDataHandler(expatParser,&CATXMLParser::CharacterHandler);
00100
00101 if (XML_Parse(expatParser,(char*)memoryBuf,bufLen,1) == XML_STATUS_ERROR)
00102 {
00103
00104 XML_ParserFree(expatParser);
00105 delete parser;
00106 return CATRESULT(CAT_ERR_XML_INVALID_XML);
00107 }
00108
00109 if (root)
00110 {
00111 root->ParseAttributes();
00112 }
00113
00114 XML_ParserFree(expatParser);
00115
00116 delete parser;
00117 return CAT_SUCCESS;
00118 }
00119
00120
00121 void XMLCALL CATXMLParser::StartElement(void *userData,
00122 const XML_Char *name,
00123 const XML_Char **atts)
00124 {
00125 CATXMLParser* parser = (CATXMLParser*)userData;
00126 CATXMLAttribs* newAttribs = new CATXMLAttribs(CATXMLObject::CATXMLKeyComp);
00127 for (CATUInt32 i = 0; atts[i]; i += 2)
00128 {
00129 CATWChar* newKey = new CATWChar[wcslen((const CATWChar*)atts[i])+1];
00130 CATWChar* newVal = new CATWChar[wcslen((const CATWChar*)atts[i+1])+1];
00131 wcscpy(newKey,atts[i]);
00132 wcscpy(newVal,atts[i+1]);
00133
00134 newAttribs->insert(std::make_pair(newKey, newVal));
00135 }
00136
00137 CATXMLObject* newObject = 0;
00138
00139 CATResult hr = parser->fFactory->Create( name, newAttribs, parser->fCurParent, newObject);
00140 if (CATFAILED(hr) || (newObject == 0))
00141 {
00142 while (newAttribs->size() != 0)
00143 {
00144 CATXMLAttribsIter iter = newAttribs->begin();
00145 delete [] (CATWChar*)iter->first;
00146 delete [] (CATWChar*)iter->second;
00147 newAttribs->erase(iter);
00148 }
00149 delete newAttribs;
00150 return;
00151 }
00152
00153 if (*parser->fRootObjPtr == 0)
00154 {
00155 *parser->fRootObjPtr = newObject;
00156 }
00157
00158 parser->fCurParent = newObject;
00159 parser->fObjectStack.push(newObject);
00160 }
00161
00162
00163 void XMLCALL CATXMLParser::CharacterHandler(void *userData,
00164 const XML_Char *s,
00165 int len)
00166 {
00167 CATXMLParser* parser = (CATXMLParser*)userData;
00168 if (parser->fCurParent)
00169 {
00170 parser->fCurParent->AppendData(s,len);
00171 }
00172 }
00173
00174
00175
00176 void XMLCALL CATXMLParser::EndElement(void *userData,
00177 const XML_Char* )
00178 {
00179 CATXMLParser* parser = (CATXMLParser*)userData;
00180 parser->fObjectStack.pop();
00181 if (parser->fObjectStack.size())
00182 {
00183 parser->fCurParent = parser->fObjectStack.top();
00184 }
00185 else
00186 {
00187 parser->fCurParent = 0;
00188 }
00189 }
00190
00191 CATResult CATXMLParser::Write(const CATString& filename, CATXMLObject* rootNode)
00192 {
00193 CATResult result = CAT_SUCCESS;
00194 CATString header = L"<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
00195 CATStreamFile xmlFile;
00196 header << kCRLF;
00197
00198 if (CATFAILED(result = xmlFile.Open(filename,CATStream::READ_WRITE_CREATE_TRUNC)))
00199 {
00200 return result;
00201 }
00202
00203 result = xmlFile.Write((const char*)header, header.Length());
00204 if (CATFAILED(result))
00205 {
00206 (void)xmlFile.Close();
00207 return result;
00208 }
00209
00210 CATXMLObject* curNode = 0;
00211 result = rootNode->WriteToStream(&xmlFile);
00212 (void)xmlFile.Close();
00213
00214 return result;
00215 }