SAX based XML parser

Dependents:   giken9_HTMLServer_Temp_Sample

Committer:
andrewbonney
Date:
Thu May 26 10:03:14 2011 +0000
Revision:
1:e96b2af301dd
Parent:
0:07919e3d6c56
Update to reduce buffer sizes

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewbonney 0:07919e3d6c56 1 // expatpp
andrewbonney 0:07919e3d6c56 2 #ifdef UNDER_CE
andrewbonney 0:07919e3d6c56 3 #include <string.h>
andrewbonney 0:07919e3d6c56 4 #include <windows.h>
andrewbonney 0:07919e3d6c56 5 #include <dbgapi.h>
andrewbonney 0:07919e3d6c56 6 #define assert ASSERT
andrewbonney 0:07919e3d6c56 7 #else
andrewbonney 0:07919e3d6c56 8 #include <string>
andrewbonney 0:07919e3d6c56 9 using namespace std;
andrewbonney 0:07919e3d6c56 10 #include <assert.h>
andrewbonney 0:07919e3d6c56 11 #endif
andrewbonney 0:07919e3d6c56 12 #include "expatpp.h"
andrewbonney 0:07919e3d6c56 13
andrewbonney 0:07919e3d6c56 14 #pragma diag_suppress 1299
andrewbonney 0:07919e3d6c56 15
andrewbonney 0:07919e3d6c56 16
andrewbonney 0:07919e3d6c56 17 // may be defined in xmltchar.h or elsewhere
andrewbonney 0:07919e3d6c56 18 #ifndef tcscmp
andrewbonney 0:07919e3d6c56 19 #ifdef XML_UNICODE
andrewbonney 0:07919e3d6c56 20 #define tcscmp wcscmp
andrewbonney 0:07919e3d6c56 21 #else
andrewbonney 0:07919e3d6c56 22 #define tcscmp strcmp
andrewbonney 0:07919e3d6c56 23 #endif // XML_UNICODE
andrewbonney 0:07919e3d6c56 24 #endif // tcscmp
andrewbonney 0:07919e3d6c56 25
andrewbonney 0:07919e3d6c56 26
andrewbonney 0:07919e3d6c56 27 #ifndef BUFSIZ
andrewbonney 1:e96b2af301dd 28 #define BUFSIZ 256 // Was 4096
andrewbonney 0:07919e3d6c56 29 #endif
andrewbonney 0:07919e3d6c56 30
andrewbonney 0:07919e3d6c56 31 expatpp::expatpp(bool createParser) :
andrewbonney 0:07919e3d6c56 32 mParser(0), // in case of exception below
andrewbonney 0:07919e3d6c56 33 mHaveParsed(false)
andrewbonney 0:07919e3d6c56 34 {
andrewbonney 0:07919e3d6c56 35 if (createParser) {
andrewbonney 0:07919e3d6c56 36 // subclasses may call this ctor after parser created!
andrewbonney 0:07919e3d6c56 37 mParser = XML_ParserCreate(0);
andrewbonney 0:07919e3d6c56 38 SetupHandlers();
andrewbonney 0:07919e3d6c56 39 }
andrewbonney 0:07919e3d6c56 40 }
andrewbonney 0:07919e3d6c56 41
andrewbonney 0:07919e3d6c56 42
andrewbonney 0:07919e3d6c56 43 void
andrewbonney 0:07919e3d6c56 44 expatpp::SetupHandlers()
andrewbonney 0:07919e3d6c56 45 {
andrewbonney 0:07919e3d6c56 46 ::XML_SetUserData(mParser, this);
andrewbonney 0:07919e3d6c56 47 ::XML_SetElementHandler(mParser, startElementCallback, endElementCallback);
andrewbonney 0:07919e3d6c56 48 ::XML_SetCharacterDataHandler(mParser, charDataCallback);
andrewbonney 0:07919e3d6c56 49 ::XML_SetProcessingInstructionHandler(mParser, processingInstructionCallback);
andrewbonney 0:07919e3d6c56 50 ::XML_SetDefaultHandler(mParser, defaultHandlerCallback);
andrewbonney 0:07919e3d6c56 51 ::XML_SetUnparsedEntityDeclHandler(mParser, unParsedEntityDeclCallback);
andrewbonney 0:07919e3d6c56 52 ::XML_SetNotationDeclHandler(mParser, notationDeclCallback);
andrewbonney 0:07919e3d6c56 53 ::XML_SetNotStandaloneHandler(mParser, notStandaloneHandlerCallback);
andrewbonney 0:07919e3d6c56 54 ::XML_SetNamespaceDeclHandler(mParser, startNamespaceCallback, endNamespaceCallback);
andrewbonney 0:07919e3d6c56 55 #ifndef EXPATPP_COMPATIBLE_EXPAT12
andrewbonney 0:07919e3d6c56 56 ::XML_SetAttlistDeclHandler(mParser, attlistDeclCallback);
andrewbonney 0:07919e3d6c56 57 ::XML_SetCdataSectionHandler(mParser, startCdataSectionCallback, endCdataSectionCallback);
andrewbonney 0:07919e3d6c56 58 ::XML_SetCommentHandler(mParser, commentCallback);
andrewbonney 0:07919e3d6c56 59 ::XML_SetDoctypeDeclHandler(mParser, startDoctypeDeclCallback, endDoctypeDeclCallback);
andrewbonney 0:07919e3d6c56 60 ::XML_SetElementDeclHandler(mParser, elementDeclCallback);
andrewbonney 0:07919e3d6c56 61 ::XML_SetEntityDeclHandler(mParser, entityDeclCallback);
andrewbonney 0:07919e3d6c56 62 ::XML_SetSkippedEntityHandler(mParser, skippedEntityCallback);
andrewbonney 0:07919e3d6c56 63 ::XML_SetXmlDeclHandler(mParser, xmlDeclCallback);
andrewbonney 0:07919e3d6c56 64 #endif
andrewbonney 0:07919e3d6c56 65 }
andrewbonney 0:07919e3d6c56 66
andrewbonney 0:07919e3d6c56 67
andrewbonney 0:07919e3d6c56 68 expatpp::~expatpp()
andrewbonney 0:07919e3d6c56 69 {
andrewbonney 0:07919e3d6c56 70 if (mParser) // allows subclasses to avoid finishing parsing
andrewbonney 0:07919e3d6c56 71 ReleaseParser();
andrewbonney 0:07919e3d6c56 72 }
andrewbonney 0:07919e3d6c56 73
andrewbonney 0:07919e3d6c56 74
andrewbonney 0:07919e3d6c56 75 /**
andrewbonney 0:07919e3d6c56 76 Provide single point that will call XML_ParserFree.
andrewbonney 0:07919e3d6c56 77 Nothing else in this code should call XML_ParserFree!
andrewbonney 0:07919e3d6c56 78 */
andrewbonney 0:07919e3d6c56 79 void
andrewbonney 0:07919e3d6c56 80 expatpp::ReleaseParser()
andrewbonney 0:07919e3d6c56 81 {
andrewbonney 0:07919e3d6c56 82 ::XML_ParserFree(mParser);
andrewbonney 0:07919e3d6c56 83 mParser = 0;
andrewbonney 0:07919e3d6c56 84 }
andrewbonney 0:07919e3d6c56 85
andrewbonney 0:07919e3d6c56 86
andrewbonney 0:07919e3d6c56 87
andrewbonney 0:07919e3d6c56 88 /**
andrewbonney 0:07919e3d6c56 89 Provide single point that will call XML_ParserReset.
andrewbonney 0:07919e3d6c56 90 Guarded against trivial reset before use in case that breaks
andrewbonney 0:07919e3d6c56 91 expat or creates overhead.
andrewbonney 0:07919e3d6c56 92
andrewbonney 0:07919e3d6c56 93 \todo pass in encoding to XML_ParserReset when we support encodings
andrewbonney 0:07919e3d6c56 94 */
andrewbonney 0:07919e3d6c56 95 void
andrewbonney 0:07919e3d6c56 96 expatpp::ResetParser()
andrewbonney 0:07919e3d6c56 97 {
andrewbonney 0:07919e3d6c56 98 #ifdef EXPATPP_COMPATIBLE_EXPAT12
andrewbonney 0:07919e3d6c56 99 assert(!"Reset not available in earlier than expat 1.95.3");s
andrewbonney 0:07919e3d6c56 100 #else
andrewbonney 0:07919e3d6c56 101 /*if (mHaveParsed) {
andrewbonney 0:07919e3d6c56 102 ::XML_ParserReset(mParser, NULL);
andrewbonney 0:07919e3d6c56 103 SetupHandlers();
andrewbonney 0:07919e3d6c56 104 mHaveParsed = false;
andrewbonney 0:07919e3d6c56 105 }*/
andrewbonney 0:07919e3d6c56 106 if (mHaveParsed) {
andrewbonney 0:07919e3d6c56 107 ReleaseParser();
andrewbonney 0:07919e3d6c56 108 mParser = XML_ParserCreate(0);
andrewbonney 0:07919e3d6c56 109 SetupHandlers();
andrewbonney 0:07919e3d6c56 110 mHaveParsed = false;
andrewbonney 0:07919e3d6c56 111 }
andrewbonney 0:07919e3d6c56 112 #endif
andrewbonney 0:07919e3d6c56 113 }
andrewbonney 0:07919e3d6c56 114
andrewbonney 0:07919e3d6c56 115
andrewbonney 0:07919e3d6c56 116 /**
andrewbonney 0:07919e3d6c56 117 Parse entire file, basically copy of the loop from the elements.c example.
andrewbonney 0:07919e3d6c56 118 */
andrewbonney 0:07919e3d6c56 119 XML_Status
andrewbonney 0:07919e3d6c56 120 expatpp::parseFile(FILE* inFile)
andrewbonney 0:07919e3d6c56 121 {
andrewbonney 0:07919e3d6c56 122 ResetParser();
andrewbonney 0:07919e3d6c56 123
andrewbonney 0:07919e3d6c56 124 char buf[BUFSIZ];
andrewbonney 0:07919e3d6c56 125 int done;
andrewbonney 0:07919e3d6c56 126 if (!inFile)
andrewbonney 0:07919e3d6c56 127 return XML_STATUS_ERROR;
andrewbonney 0:07919e3d6c56 128 fseek(inFile, 0, SEEK_SET); // reset for reading
andrewbonney 0:07919e3d6c56 129 do {
andrewbonney 0:07919e3d6c56 130 size_t len = fread(buf, 1, sizeof(buf), inFile);
andrewbonney 0:07919e3d6c56 131 done = len < sizeof(buf);
andrewbonney 0:07919e3d6c56 132 enum XML_Status parseStatus;
andrewbonney 0:07919e3d6c56 133 if ((parseStatus = XML_Parse(buf, len, done))!=XML_STATUS_OK) {
andrewbonney 0:07919e3d6c56 134 return parseStatus;
andrewbonney 0:07919e3d6c56 135 }
andrewbonney 0:07919e3d6c56 136 } while (!done);
andrewbonney 0:07919e3d6c56 137 return XML_STATUS_OK;
andrewbonney 0:07919e3d6c56 138 }
andrewbonney 0:07919e3d6c56 139
andrewbonney 0:07919e3d6c56 140
andrewbonney 0:07919e3d6c56 141 XML_Status
andrewbonney 0:07919e3d6c56 142 expatpp::XML_Parse(const char *s, int len, int isFinal)
andrewbonney 0:07919e3d6c56 143 {
andrewbonney 0:07919e3d6c56 144 mHaveParsed = true;
andrewbonney 0:07919e3d6c56 145 const XML_Status retStatus = ::XML_Parse(mParser, s, len, isFinal);
andrewbonney 0:07919e3d6c56 146 if (isFinal)
andrewbonney 0:07919e3d6c56 147 CheckFinalStatus(retStatus);
andrewbonney 0:07919e3d6c56 148 return retStatus;
andrewbonney 0:07919e3d6c56 149 }
andrewbonney 0:07919e3d6c56 150
andrewbonney 0:07919e3d6c56 151
andrewbonney 0:07919e3d6c56 152 XML_Error
andrewbonney 0:07919e3d6c56 153 expatpp::XML_GetErrorCode()
andrewbonney 0:07919e3d6c56 154 {
andrewbonney 0:07919e3d6c56 155 return ::XML_GetErrorCode(mParser);
andrewbonney 0:07919e3d6c56 156 }
andrewbonney 0:07919e3d6c56 157
andrewbonney 0:07919e3d6c56 158
andrewbonney 0:07919e3d6c56 159 int
andrewbonney 0:07919e3d6c56 160 expatpp::XML_GetCurrentLineNumber()
andrewbonney 0:07919e3d6c56 161 {
andrewbonney 0:07919e3d6c56 162 return ::XML_GetCurrentLineNumber(mParser);
andrewbonney 0:07919e3d6c56 163 }
andrewbonney 0:07919e3d6c56 164
andrewbonney 0:07919e3d6c56 165
andrewbonney 0:07919e3d6c56 166 int
andrewbonney 0:07919e3d6c56 167 expatpp::XML_GetCurrentColumnNumber()
andrewbonney 0:07919e3d6c56 168 {
andrewbonney 0:07919e3d6c56 169 return ::XML_GetCurrentColumnNumber(mParser);
andrewbonney 0:07919e3d6c56 170 }
andrewbonney 0:07919e3d6c56 171
andrewbonney 0:07919e3d6c56 172
andrewbonney 0:07919e3d6c56 173
andrewbonney 0:07919e3d6c56 174
andrewbonney 0:07919e3d6c56 175 /**
andrewbonney 0:07919e3d6c56 176 Parse string which is assumed to be entire XML document.
andrewbonney 0:07919e3d6c56 177 Written to stop stupid errors of being off by one in the string length causing
andrewbonney 0:07919e3d6c56 178 wasted debugging time, such as:
andrewbonney 0:07919e3d6c56 179 \verbatim
andrewbonney 0:07919e3d6c56 180 const char[] kSampleSettings = "<settings/>";
andrewbonney 0:07919e3d6c56 181 const int sampleSize = sizeof(kSampleSettings)-1; // unless you remember to subtract one here will get invalid token error
andrewbonney 0:07919e3d6c56 182 if (!parser.XML_Parse(kSampleSettings, sampleSize, 1)) {
andrewbonney 0:07919e3d6c56 183 \endverbatim
andrewbonney 0:07919e3d6c56 184 */
andrewbonney 0:07919e3d6c56 185 XML_Status
andrewbonney 0:07919e3d6c56 186 expatpp::parseString(const char* inString)
andrewbonney 0:07919e3d6c56 187 {
andrewbonney 0:07919e3d6c56 188 ResetParser();
andrewbonney 0:07919e3d6c56 189 const int inLen = strlen(inString);
andrewbonney 0:07919e3d6c56 190 return XML_Parse(inString, inLen, 1);
andrewbonney 0:07919e3d6c56 191 }
andrewbonney 0:07919e3d6c56 192
andrewbonney 0:07919e3d6c56 193 void
andrewbonney 0:07919e3d6c56 194 expatpp::startElementCallback(void *userData, const XML_Char* name, const XML_Char** atts)
andrewbonney 0:07919e3d6c56 195 {
andrewbonney 0:07919e3d6c56 196 ((expatpp*)userData)->startElement(name, atts);
andrewbonney 0:07919e3d6c56 197 }
andrewbonney 0:07919e3d6c56 198
andrewbonney 0:07919e3d6c56 199
andrewbonney 0:07919e3d6c56 200 void
andrewbonney 0:07919e3d6c56 201 expatpp::endElementCallback(void *userData, const XML_Char* name)
andrewbonney 0:07919e3d6c56 202 {
andrewbonney 0:07919e3d6c56 203 ((expatpp*)userData)->endElement(name);
andrewbonney 0:07919e3d6c56 204 }
andrewbonney 0:07919e3d6c56 205
andrewbonney 0:07919e3d6c56 206
andrewbonney 0:07919e3d6c56 207 void
andrewbonney 0:07919e3d6c56 208 expatpp::startNamespaceCallback(void *userData, const XML_Char* prefix, const XML_Char* uri)
andrewbonney 0:07919e3d6c56 209 {
andrewbonney 0:07919e3d6c56 210 ((expatpp*)userData)->startNamespace(prefix, uri);
andrewbonney 0:07919e3d6c56 211 }
andrewbonney 0:07919e3d6c56 212
andrewbonney 0:07919e3d6c56 213
andrewbonney 0:07919e3d6c56 214 void
andrewbonney 0:07919e3d6c56 215 expatpp::endNamespaceCallback(void *userData, const XML_Char* prefix)
andrewbonney 0:07919e3d6c56 216 {
andrewbonney 0:07919e3d6c56 217 ((expatpp*)userData)->endNamespace(prefix);
andrewbonney 0:07919e3d6c56 218 }
andrewbonney 0:07919e3d6c56 219
andrewbonney 0:07919e3d6c56 220
andrewbonney 0:07919e3d6c56 221 void
andrewbonney 0:07919e3d6c56 222 expatpp::charDataCallback(void *userData, const XML_Char* s, int len)
andrewbonney 0:07919e3d6c56 223 {
andrewbonney 0:07919e3d6c56 224 ((expatpp*)userData)->charData(s, len);
andrewbonney 0:07919e3d6c56 225 }
andrewbonney 0:07919e3d6c56 226
andrewbonney 0:07919e3d6c56 227
andrewbonney 0:07919e3d6c56 228 void
andrewbonney 0:07919e3d6c56 229 expatpp:: processingInstructionCallback(void *userData, const XML_Char* target, const XML_Char* data)
andrewbonney 0:07919e3d6c56 230 {
andrewbonney 0:07919e3d6c56 231 ((expatpp*)userData)->processingInstruction(target, data);
andrewbonney 0:07919e3d6c56 232 }
andrewbonney 0:07919e3d6c56 233
andrewbonney 0:07919e3d6c56 234
andrewbonney 0:07919e3d6c56 235 void
andrewbonney 0:07919e3d6c56 236 expatpp::defaultHandlerCallback(void* userData, const XML_Char* s, int len)
andrewbonney 0:07919e3d6c56 237 {
andrewbonney 0:07919e3d6c56 238 ((expatpp*)userData)->defaultHandler(s, len);
andrewbonney 0:07919e3d6c56 239 }
andrewbonney 0:07919e3d6c56 240
andrewbonney 0:07919e3d6c56 241
andrewbonney 0:07919e3d6c56 242 int
andrewbonney 0:07919e3d6c56 243 expatpp::notStandaloneHandlerCallback(void* userData)
andrewbonney 0:07919e3d6c56 244 {
andrewbonney 0:07919e3d6c56 245 return ((expatpp*)userData)->notStandaloneHandler();
andrewbonney 0:07919e3d6c56 246 }
andrewbonney 0:07919e3d6c56 247
andrewbonney 0:07919e3d6c56 248
andrewbonney 0:07919e3d6c56 249 void
andrewbonney 0:07919e3d6c56 250 expatpp::unParsedEntityDeclCallback(void* userData, const XML_Char* entityName, const XML_Char* base, const XML_Char* systemId, const XML_Char* publicId, const XML_Char* notationName)
andrewbonney 0:07919e3d6c56 251 {
andrewbonney 0:07919e3d6c56 252 ((expatpp*)userData)->unparsedEntityDecl(entityName, base, systemId, publicId, notationName);
andrewbonney 0:07919e3d6c56 253 }
andrewbonney 0:07919e3d6c56 254
andrewbonney 0:07919e3d6c56 255
andrewbonney 0:07919e3d6c56 256 void
andrewbonney 0:07919e3d6c56 257 expatpp::notationDeclCallback(void *userData, const XML_Char* notationName, const XML_Char* base, const XML_Char* systemId, const XML_Char* publicId)
andrewbonney 0:07919e3d6c56 258 {
andrewbonney 0:07919e3d6c56 259 ((expatpp*)userData)->notationDecl(notationName, base, systemId, publicId);
andrewbonney 0:07919e3d6c56 260 }
andrewbonney 0:07919e3d6c56 261
andrewbonney 0:07919e3d6c56 262
andrewbonney 0:07919e3d6c56 263 void
andrewbonney 0:07919e3d6c56 264 expatpp::startElement(const XML_Char*, const XML_Char**)
andrewbonney 0:07919e3d6c56 265 {}
andrewbonney 0:07919e3d6c56 266
andrewbonney 0:07919e3d6c56 267
andrewbonney 0:07919e3d6c56 268 void
andrewbonney 0:07919e3d6c56 269 expatpp::endElement(const XML_Char*)
andrewbonney 0:07919e3d6c56 270 {}
andrewbonney 0:07919e3d6c56 271
andrewbonney 0:07919e3d6c56 272
andrewbonney 0:07919e3d6c56 273 void
andrewbonney 0:07919e3d6c56 274 expatpp::startNamespace(const XML_Char* /* prefix */, const XML_Char* /* uri */)
andrewbonney 0:07919e3d6c56 275 {}
andrewbonney 0:07919e3d6c56 276
andrewbonney 0:07919e3d6c56 277
andrewbonney 0:07919e3d6c56 278 void
andrewbonney 0:07919e3d6c56 279 expatpp::endNamespace(const XML_Char*)
andrewbonney 0:07919e3d6c56 280 {}
andrewbonney 0:07919e3d6c56 281
andrewbonney 0:07919e3d6c56 282
andrewbonney 0:07919e3d6c56 283 void
andrewbonney 0:07919e3d6c56 284 expatpp::charData(const XML_Char*, int )
andrewbonney 0:07919e3d6c56 285 {
andrewbonney 0:07919e3d6c56 286 }
andrewbonney 0:07919e3d6c56 287
andrewbonney 0:07919e3d6c56 288
andrewbonney 0:07919e3d6c56 289 void
andrewbonney 0:07919e3d6c56 290 expatpp::processingInstruction(const XML_Char*, const XML_Char*)
andrewbonney 0:07919e3d6c56 291 {
andrewbonney 0:07919e3d6c56 292 }
andrewbonney 0:07919e3d6c56 293
andrewbonney 0:07919e3d6c56 294
andrewbonney 0:07919e3d6c56 295 void
andrewbonney 0:07919e3d6c56 296 expatpp::defaultHandler(const XML_Char*, int)
andrewbonney 0:07919e3d6c56 297 {
andrewbonney 0:07919e3d6c56 298 }
andrewbonney 0:07919e3d6c56 299
andrewbonney 0:07919e3d6c56 300
andrewbonney 0:07919e3d6c56 301 int
andrewbonney 0:07919e3d6c56 302 expatpp::notStandaloneHandler()
andrewbonney 0:07919e3d6c56 303 {
andrewbonney 0:07919e3d6c56 304 return 0;
andrewbonney 0:07919e3d6c56 305 }
andrewbonney 0:07919e3d6c56 306
andrewbonney 0:07919e3d6c56 307
andrewbonney 0:07919e3d6c56 308 void
andrewbonney 0:07919e3d6c56 309 expatpp::unparsedEntityDecl(const XML_Char*, const XML_Char*, const XML_Char*, const XML_Char*, const XML_Char*)
andrewbonney 0:07919e3d6c56 310 {
andrewbonney 0:07919e3d6c56 311 }
andrewbonney 0:07919e3d6c56 312
andrewbonney 0:07919e3d6c56 313
andrewbonney 0:07919e3d6c56 314 void
andrewbonney 0:07919e3d6c56 315 expatpp::notationDecl(const XML_Char*, const XML_Char*, const XML_Char*, const XML_Char*)
andrewbonney 0:07919e3d6c56 316 {
andrewbonney 0:07919e3d6c56 317 }
andrewbonney 0:07919e3d6c56 318
andrewbonney 0:07919e3d6c56 319
andrewbonney 0:07919e3d6c56 320 int
andrewbonney 0:07919e3d6c56 321 expatpp::skipWhiteSpace(const XML_Char* startFrom)
andrewbonney 0:07919e3d6c56 322 {
andrewbonney 0:07919e3d6c56 323 // use our own XML definition of white space
andrewbonney 0:07919e3d6c56 324 // TO DO - confirm this is correct!
andrewbonney 0:07919e3d6c56 325 const XML_Char* s = startFrom;
andrewbonney 0:07919e3d6c56 326 XML_Char c = *s;
andrewbonney 0:07919e3d6c56 327 while ((c==' ') || (c=='\t') || (c=='\n') || (c=='\r')) {
andrewbonney 0:07919e3d6c56 328 s++;
andrewbonney 0:07919e3d6c56 329 c = *s;
andrewbonney 0:07919e3d6c56 330 }
andrewbonney 0:07919e3d6c56 331 const int numSkipped = s - startFrom;
andrewbonney 0:07919e3d6c56 332 return numSkipped;
andrewbonney 0:07919e3d6c56 333 }
andrewbonney 0:07919e3d6c56 334
andrewbonney 0:07919e3d6c56 335
andrewbonney 0:07919e3d6c56 336 /**
andrewbonney 0:07919e3d6c56 337 Iterate the paired attribute name/value until find a pair with matching name.
andrewbonney 0:07919e3d6c56 338 \return pointer to the value or null if not found.
andrewbonney 0:07919e3d6c56 339 */
andrewbonney 0:07919e3d6c56 340 const XML_Char*
andrewbonney 0:07919e3d6c56 341 expatpp::getAttribute(const XML_Char* matchingName, const XML_Char** atts)
andrewbonney 0:07919e3d6c56 342 {
andrewbonney 0:07919e3d6c56 343 for (int i=0; atts[i]; i++) {
andrewbonney 0:07919e3d6c56 344 const XML_Char* attributeName = atts[i++];
andrewbonney 0:07919e3d6c56 345 assert(attributeName); // shouldn't fail this because of loop test above
andrewbonney 0:07919e3d6c56 346 if(tcscmp(attributeName, matchingName)==0) {
andrewbonney 0:07919e3d6c56 347 return atts[i]; // if 2nd item was missing, this returns 0 safely indicating failure
andrewbonney 0:07919e3d6c56 348 }
andrewbonney 0:07919e3d6c56 349 }
andrewbonney 0:07919e3d6c56 350 return 0;
andrewbonney 0:07919e3d6c56 351 }
andrewbonney 0:07919e3d6c56 352
andrewbonney 0:07919e3d6c56 353
andrewbonney 0:07919e3d6c56 354 /**
andrewbonney 0:07919e3d6c56 355 \bug will always return 0 for PPC
andrewbonney 0:07919e3d6c56 356 */
andrewbonney 0:07919e3d6c56 357 bool
andrewbonney 0:07919e3d6c56 358 expatpp::getIntegerAttribute(const XML_Char *matchingName, const XML_Char **atts, int& outAtt)
andrewbonney 0:07919e3d6c56 359 {
andrewbonney 0:07919e3d6c56 360 const XML_Char* attStr = getAttribute(matchingName, atts);
andrewbonney 0:07919e3d6c56 361 if (!attStr)
andrewbonney 0:07919e3d6c56 362 return false;
andrewbonney 0:07919e3d6c56 363 int i=0;
andrewbonney 0:07919e3d6c56 364 #ifdef XML_UNICODE
andrewbonney 0:07919e3d6c56 365 fail to compile because need this now
andrewbonney 0:07919e3d6c56 366 #else
andrewbonney 0:07919e3d6c56 367 sscanf(attStr, "%d", &i);
andrewbonney 0:07919e3d6c56 368 #endif
andrewbonney 0:07919e3d6c56 369 outAtt = i;
andrewbonney 0:07919e3d6c56 370 return true;
andrewbonney 0:07919e3d6c56 371 }
andrewbonney 0:07919e3d6c56 372
andrewbonney 0:07919e3d6c56 373
andrewbonney 0:07919e3d6c56 374 /**
andrewbonney 0:07919e3d6c56 375 \bug will always return 0 for PPC
andrewbonney 0:07919e3d6c56 376 */
andrewbonney 0:07919e3d6c56 377 bool
andrewbonney 0:07919e3d6c56 378 expatpp::getDoubleAttribute(const XML_Char *matchingName, const XML_Char **atts, double& outAtt)
andrewbonney 0:07919e3d6c56 379 {
andrewbonney 0:07919e3d6c56 380 const XML_Char* attStr = getAttribute(matchingName, atts);
andrewbonney 0:07919e3d6c56 381 if (!attStr)
andrewbonney 0:07919e3d6c56 382 return false;
andrewbonney 0:07919e3d6c56 383 float f = 0.0; // sscanf doesn't allow point to double
andrewbonney 0:07919e3d6c56 384 #ifdef XML_UNICODE
andrewbonney 0:07919e3d6c56 385 fail to compile because need this now
andrewbonney 0:07919e3d6c56 386 #else
andrewbonney 0:07919e3d6c56 387 sscanf(attStr, "%f", &f);
andrewbonney 0:07919e3d6c56 388 #endif
andrewbonney 0:07919e3d6c56 389 outAtt = f;
andrewbonney 0:07919e3d6c56 390 return true;
andrewbonney 0:07919e3d6c56 391 }
andrewbonney 0:07919e3d6c56 392
andrewbonney 0:07919e3d6c56 393
andrewbonney 0:07919e3d6c56 394 bool
andrewbonney 0:07919e3d6c56 395 expatpp::emptyCharData(const XML_Char *s, int len)
andrewbonney 0:07919e3d6c56 396 {
andrewbonney 0:07919e3d6c56 397 // usually call from top of overriden charData methods
andrewbonney 0:07919e3d6c56 398 if (len==0)
andrewbonney 0:07919e3d6c56 399 return true; //*** early exit - empty string, may never occur??
andrewbonney 0:07919e3d6c56 400
andrewbonney 0:07919e3d6c56 401 // skip newline and empty whitespace
andrewbonney 0:07919e3d6c56 402 if (
andrewbonney 0:07919e3d6c56 403 ((len==1) && ( (s[0]=='\n') || (s[0]=='\r')) ) || // just CR or just LF
andrewbonney 0:07919e3d6c56 404 ((len==2) && (s[0]=='\r') && (s[1]=='\n')) // DOS-style CRLF
andrewbonney 0:07919e3d6c56 405 )
andrewbonney 0:07919e3d6c56 406 return true; //*** early exit - newline
andrewbonney 0:07919e3d6c56 407
andrewbonney 0:07919e3d6c56 408 const int lastCharAt = len-1;
andrewbonney 0:07919e3d6c56 409 if (s[lastCharAt]==' ') { // maybe all whitespace
andrewbonney 0:07919e3d6c56 410 int i;
andrewbonney 0:07919e3d6c56 411 for (i=0; i<lastCharAt; i++) {
andrewbonney 0:07919e3d6c56 412 if (s[i]!=' ')
andrewbonney 0:07919e3d6c56 413 break;
andrewbonney 0:07919e3d6c56 414 }
andrewbonney 0:07919e3d6c56 415 if (i==lastCharAt)
andrewbonney 0:07919e3d6c56 416 return true; //*** early exit - all spaces
andrewbonney 0:07919e3d6c56 417 }
andrewbonney 0:07919e3d6c56 418 return false;
andrewbonney 0:07919e3d6c56 419 }
andrewbonney 0:07919e3d6c56 420
andrewbonney 0:07919e3d6c56 421
andrewbonney 0:07919e3d6c56 422 //-------- Added for expat 1.95.5---------------
andrewbonney 0:07919e3d6c56 423 void
andrewbonney 0:07919e3d6c56 424 expatpp::attlistDeclCallback(void *userData,
andrewbonney 0:07919e3d6c56 425 const XML_Char *elname,
andrewbonney 0:07919e3d6c56 426 const XML_Char *attname,
andrewbonney 0:07919e3d6c56 427 const XML_Char *att_type,
andrewbonney 0:07919e3d6c56 428 const XML_Char *dflt,
andrewbonney 0:07919e3d6c56 429 int isrequired)
andrewbonney 0:07919e3d6c56 430 {
andrewbonney 0:07919e3d6c56 431 ((expatpp*)userData)->attlistDecl(elname, attname, att_type, dflt, isrequired);
andrewbonney 0:07919e3d6c56 432 }
andrewbonney 0:07919e3d6c56 433
andrewbonney 0:07919e3d6c56 434
andrewbonney 0:07919e3d6c56 435 void
andrewbonney 0:07919e3d6c56 436 expatpp::commentCallback(void *userData, const XML_Char *data)
andrewbonney 0:07919e3d6c56 437 {
andrewbonney 0:07919e3d6c56 438 ((expatpp*)userData)->comment(data);
andrewbonney 0:07919e3d6c56 439 }
andrewbonney 0:07919e3d6c56 440
andrewbonney 0:07919e3d6c56 441
andrewbonney 0:07919e3d6c56 442 void
andrewbonney 0:07919e3d6c56 443 expatpp::elementDeclCallback(void *userData, const XML_Char *name, XML_Content *model)
andrewbonney 0:07919e3d6c56 444 {
andrewbonney 0:07919e3d6c56 445 ((expatpp*)userData)->elementDecl(name, model);
andrewbonney 0:07919e3d6c56 446 }
andrewbonney 0:07919e3d6c56 447
andrewbonney 0:07919e3d6c56 448
andrewbonney 0:07919e3d6c56 449 void
andrewbonney 0:07919e3d6c56 450 expatpp::endCdataSectionCallback(void *userData)
andrewbonney 0:07919e3d6c56 451 {
andrewbonney 0:07919e3d6c56 452 ((expatpp*)userData)->endCdataSection();
andrewbonney 0:07919e3d6c56 453 }
andrewbonney 0:07919e3d6c56 454
andrewbonney 0:07919e3d6c56 455
andrewbonney 0:07919e3d6c56 456 void
andrewbonney 0:07919e3d6c56 457 expatpp::endDoctypeDeclCallback(void *userData)
andrewbonney 0:07919e3d6c56 458 {
andrewbonney 0:07919e3d6c56 459 ((expatpp*)userData)->endDoctypeDecl();
andrewbonney 0:07919e3d6c56 460 }
andrewbonney 0:07919e3d6c56 461
andrewbonney 0:07919e3d6c56 462
andrewbonney 0:07919e3d6c56 463 void
andrewbonney 0:07919e3d6c56 464 expatpp::entityDeclCallback(void *userData,
andrewbonney 0:07919e3d6c56 465 const XML_Char *entityName,
andrewbonney 0:07919e3d6c56 466 int is_parameter_entity,
andrewbonney 0:07919e3d6c56 467 const XML_Char *value,
andrewbonney 0:07919e3d6c56 468 int value_length,
andrewbonney 0:07919e3d6c56 469 const XML_Char *base,
andrewbonney 0:07919e3d6c56 470 const XML_Char *systemId,
andrewbonney 0:07919e3d6c56 471 const XML_Char *publicId,
andrewbonney 0:07919e3d6c56 472 const XML_Char *notationName)
andrewbonney 0:07919e3d6c56 473 {
andrewbonney 0:07919e3d6c56 474 ((expatpp*)userData)->entityDecl(entityName, is_parameter_entity, value, value_length, base, systemId, publicId, notationName);
andrewbonney 0:07919e3d6c56 475 }
andrewbonney 0:07919e3d6c56 476
andrewbonney 0:07919e3d6c56 477
andrewbonney 0:07919e3d6c56 478 void
andrewbonney 0:07919e3d6c56 479 expatpp::skippedEntityCallback(void *userData, const XML_Char *entityName, int is_parameter_entity)
andrewbonney 0:07919e3d6c56 480 {
andrewbonney 0:07919e3d6c56 481 ((expatpp*)userData)->skippedEntity(entityName, is_parameter_entity);
andrewbonney 0:07919e3d6c56 482 }
andrewbonney 0:07919e3d6c56 483
andrewbonney 0:07919e3d6c56 484
andrewbonney 0:07919e3d6c56 485 void
andrewbonney 0:07919e3d6c56 486 expatpp::startCdataSectionCallback(void *userData)
andrewbonney 0:07919e3d6c56 487 {
andrewbonney 0:07919e3d6c56 488 ((expatpp*)userData)->startCdataSection();
andrewbonney 0:07919e3d6c56 489 }
andrewbonney 0:07919e3d6c56 490
andrewbonney 0:07919e3d6c56 491
andrewbonney 0:07919e3d6c56 492 void
andrewbonney 0:07919e3d6c56 493 expatpp::startDoctypeDeclCallback(void *userData,
andrewbonney 0:07919e3d6c56 494 const XML_Char *doctypeName,
andrewbonney 0:07919e3d6c56 495 const XML_Char *sysid,
andrewbonney 0:07919e3d6c56 496 const XML_Char *pubid,
andrewbonney 0:07919e3d6c56 497 int has_internal_subset)
andrewbonney 0:07919e3d6c56 498 {
andrewbonney 0:07919e3d6c56 499 ((expatpp*)userData)->startDoctypeDecl(doctypeName, sysid, pubid, has_internal_subset);
andrewbonney 0:07919e3d6c56 500 }
andrewbonney 0:07919e3d6c56 501
andrewbonney 0:07919e3d6c56 502
andrewbonney 0:07919e3d6c56 503 void
andrewbonney 0:07919e3d6c56 504 expatpp::xmlDeclCallback(void *userData, const XML_Char *version,
andrewbonney 0:07919e3d6c56 505 const XML_Char *encoding,
andrewbonney 0:07919e3d6c56 506 int standalone)
andrewbonney 0:07919e3d6c56 507 {
andrewbonney 0:07919e3d6c56 508 ((expatpp*)userData)->xmlDecl(version, encoding, standalone);
andrewbonney 0:07919e3d6c56 509 }
andrewbonney 0:07919e3d6c56 510
andrewbonney 0:07919e3d6c56 511
andrewbonney 0:07919e3d6c56 512 void
andrewbonney 0:07919e3d6c56 513 expatpp::attlistDecl(
andrewbonney 0:07919e3d6c56 514 const XML_Char *elname,
andrewbonney 0:07919e3d6c56 515 const XML_Char *attname,
andrewbonney 0:07919e3d6c56 516 const XML_Char *att_type,
andrewbonney 0:07919e3d6c56 517 const XML_Char *dflt,
andrewbonney 0:07919e3d6c56 518 int isrequired)
andrewbonney 0:07919e3d6c56 519 {
andrewbonney 0:07919e3d6c56 520 }
andrewbonney 0:07919e3d6c56 521
andrewbonney 0:07919e3d6c56 522
andrewbonney 0:07919e3d6c56 523 void
andrewbonney 0:07919e3d6c56 524 expatpp::comment( const XML_Char *data)
andrewbonney 0:07919e3d6c56 525 {
andrewbonney 0:07919e3d6c56 526 }
andrewbonney 0:07919e3d6c56 527
andrewbonney 0:07919e3d6c56 528
andrewbonney 0:07919e3d6c56 529 void
andrewbonney 0:07919e3d6c56 530 expatpp::elementDecl( const XML_Char *name, XML_Content *model)
andrewbonney 0:07919e3d6c56 531 {
andrewbonney 0:07919e3d6c56 532 }
andrewbonney 0:07919e3d6c56 533
andrewbonney 0:07919e3d6c56 534
andrewbonney 0:07919e3d6c56 535 void
andrewbonney 0:07919e3d6c56 536 expatpp::endCdataSection()
andrewbonney 0:07919e3d6c56 537 {
andrewbonney 0:07919e3d6c56 538 }
andrewbonney 0:07919e3d6c56 539
andrewbonney 0:07919e3d6c56 540
andrewbonney 0:07919e3d6c56 541 void
andrewbonney 0:07919e3d6c56 542 expatpp::endDoctypeDecl()
andrewbonney 0:07919e3d6c56 543 {
andrewbonney 0:07919e3d6c56 544 }
andrewbonney 0:07919e3d6c56 545
andrewbonney 0:07919e3d6c56 546
andrewbonney 0:07919e3d6c56 547 void
andrewbonney 0:07919e3d6c56 548 expatpp::entityDecl(
andrewbonney 0:07919e3d6c56 549 const XML_Char *entityName,
andrewbonney 0:07919e3d6c56 550 int is_parameter_entity,
andrewbonney 0:07919e3d6c56 551 const XML_Char *value,
andrewbonney 0:07919e3d6c56 552 int value_length,
andrewbonney 0:07919e3d6c56 553 const XML_Char *base,
andrewbonney 0:07919e3d6c56 554 const XML_Char *systemId,
andrewbonney 0:07919e3d6c56 555 const XML_Char *publicId,
andrewbonney 0:07919e3d6c56 556 const XML_Char *notationName)
andrewbonney 0:07919e3d6c56 557 {
andrewbonney 0:07919e3d6c56 558 }
andrewbonney 0:07919e3d6c56 559
andrewbonney 0:07919e3d6c56 560
andrewbonney 0:07919e3d6c56 561 void
andrewbonney 0:07919e3d6c56 562 expatpp::skippedEntity( const XML_Char *entityName, int is_parameter_entity)
andrewbonney 0:07919e3d6c56 563 {
andrewbonney 0:07919e3d6c56 564 }
andrewbonney 0:07919e3d6c56 565
andrewbonney 0:07919e3d6c56 566
andrewbonney 0:07919e3d6c56 567 void
andrewbonney 0:07919e3d6c56 568 expatpp::startCdataSection()
andrewbonney 0:07919e3d6c56 569 {
andrewbonney 0:07919e3d6c56 570 }
andrewbonney 0:07919e3d6c56 571
andrewbonney 0:07919e3d6c56 572
andrewbonney 0:07919e3d6c56 573 void
andrewbonney 0:07919e3d6c56 574 expatpp::startDoctypeDecl(const XML_Char *doctypeName,
andrewbonney 0:07919e3d6c56 575 const XML_Char *sysid,
andrewbonney 0:07919e3d6c56 576 const XML_Char *pubid,
andrewbonney 0:07919e3d6c56 577 int has_internal_subset)
andrewbonney 0:07919e3d6c56 578 {
andrewbonney 0:07919e3d6c56 579 }
andrewbonney 0:07919e3d6c56 580
andrewbonney 0:07919e3d6c56 581
andrewbonney 0:07919e3d6c56 582 void
andrewbonney 0:07919e3d6c56 583 expatpp::xmlDecl( const XML_Char *version,
andrewbonney 0:07919e3d6c56 584 const XML_Char *encoding,
andrewbonney 0:07919e3d6c56 585 int standalone)
andrewbonney 0:07919e3d6c56 586 {
andrewbonney 0:07919e3d6c56 587 }
andrewbonney 0:07919e3d6c56 588
andrewbonney 0:07919e3d6c56 589
andrewbonney 0:07919e3d6c56 590
andrewbonney 0:07919e3d6c56 591
andrewbonney 0:07919e3d6c56 592 // -------------------------------------------------------
andrewbonney 0:07919e3d6c56 593 // e x p a t p p N e s t i n g
andrewbonney 0:07919e3d6c56 594 // -------------------------------------------------------
andrewbonney 0:07919e3d6c56 595 /**
andrewbonney 0:07919e3d6c56 596 \param parent can be null in which case this is root parser
andrewbonney 0:07919e3d6c56 597
andrewbonney 0:07919e3d6c56 598 \note The handlers set in here MUST be also set in SetupHandlers
andrewbonney 0:07919e3d6c56 599 which is a virtual method invoked by expatpp::ResetParser. Otherwise
andrewbonney 0:07919e3d6c56 600 you can have subtle bugs with a nested parser not properly returning
andrewbonney 0:07919e3d6c56 601 after reusing a parser (nasty and found rapidly only via extensive unit
andrewbonney 0:07919e3d6c56 602 tests and plentiful assertions!).
andrewbonney 0:07919e3d6c56 603
andrewbonney 0:07919e3d6c56 604 \WARNING
andrewbonney 0:07919e3d6c56 605 The assumption that is not obvious here is that if you want to use
andrewbonney 0:07919e3d6c56 606 nested parsers, then your topmost parser must also be an expatppNesting
andrewbonney 0:07919e3d6c56 607 subclass, NOT an expatpp subclass, because we need the
andrewbonney 0:07919e3d6c56 608 nestedStartElementCallback and nestedEndElementCallback
andrewbonney 0:07919e3d6c56 609 callbacks to override those in the expatpp ctor.
andrewbonney 0:07919e3d6c56 610
andrewbonney 0:07919e3d6c56 611
andrewbonney 0:07919e3d6c56 612
andrewbonney 0:07919e3d6c56 613 \todo go back over code in detail and confirm above warning still valid
andrewbonney 0:07919e3d6c56 614 I think if we used expat's functions to invoke the registered callback
andrewbonney 0:07919e3d6c56 615 might be safer - the explicit function call we have in nestedEndElementCallback
andrewbonney 0:07919e3d6c56 616 certainly assumes the parent type.
andrewbonney 0:07919e3d6c56 617 */
andrewbonney 0:07919e3d6c56 618 expatppNesting::expatppNesting(expatppNesting* parent) :
andrewbonney 0:07919e3d6c56 619 expatpp(parent==0), // don't create parser - we're taking over from parent if given
andrewbonney 0:07919e3d6c56 620 mDepth(0),
andrewbonney 0:07919e3d6c56 621 mParent(parent),
andrewbonney 0:07919e3d6c56 622 mOwnedChild(0),
andrewbonney 0:07919e3d6c56 623 mSelfDeleting(true)
andrewbonney 0:07919e3d6c56 624 {
andrewbonney 0:07919e3d6c56 625 if ( parent )
andrewbonney 0:07919e3d6c56 626 {
andrewbonney 0:07919e3d6c56 627 RegisterWithParentXMLParser();
andrewbonney 0:07919e3d6c56 628 parent->AdoptChild(this);
andrewbonney 0:07919e3d6c56 629 }
andrewbonney 0:07919e3d6c56 630 else
andrewbonney 0:07919e3d6c56 631 {
andrewbonney 0:07919e3d6c56 632 // No parent - the expatpp constructor will have created a new mParser (expat parser)
andrewbonney 0:07919e3d6c56 633 ::XML_SetElementHandler(mParser, nestedStartElementCallback, nestedEndElementCallback);
andrewbonney 0:07919e3d6c56 634 }
andrewbonney 0:07919e3d6c56 635 assert(mParser); // either we created above or expatpp
andrewbonney 0:07919e3d6c56 636 }
andrewbonney 0:07919e3d6c56 637
andrewbonney 0:07919e3d6c56 638
andrewbonney 0:07919e3d6c56 639 expatppNesting::~expatppNesting()
andrewbonney 0:07919e3d6c56 640 {
andrewbonney 0:07919e3d6c56 641 assert(!mParent); // if we are a sub-parser, should not delete without calling returnToParent
andrewbonney 0:07919e3d6c56 642 DeleteChild();
andrewbonney 0:07919e3d6c56 643 }
andrewbonney 0:07919e3d6c56 644
andrewbonney 0:07919e3d6c56 645
andrewbonney 0:07919e3d6c56 646 /**
andrewbonney 0:07919e3d6c56 647 Call parent version then override same as in our ctor.
andrewbonney 0:07919e3d6c56 648 */
andrewbonney 0:07919e3d6c56 649 void
andrewbonney 0:07919e3d6c56 650 expatppNesting::SetupHandlers()
andrewbonney 0:07919e3d6c56 651 {
andrewbonney 0:07919e3d6c56 652 expatpp::SetupHandlers();
andrewbonney 0:07919e3d6c56 653 ::XML_SetElementHandler(mParser, nestedStartElementCallback, nestedEndElementCallback);
andrewbonney 0:07919e3d6c56 654 }
andrewbonney 0:07919e3d6c56 655
andrewbonney 0:07919e3d6c56 656 /**
andrewbonney 0:07919e3d6c56 657 Must use if you have adopted a child parser and want to dispose of it early.
andrewbonney 0:07919e3d6c56 658 */
andrewbonney 0:07919e3d6c56 659 void
andrewbonney 0:07919e3d6c56 660 expatppNesting::DeleteChild()
andrewbonney 0:07919e3d6c56 661 {
andrewbonney 0:07919e3d6c56 662 delete mOwnedChild;
andrewbonney 0:07919e3d6c56 663 mOwnedChild = 0;
andrewbonney 0:07919e3d6c56 664 }
andrewbonney 0:07919e3d6c56 665
andrewbonney 0:07919e3d6c56 666
andrewbonney 0:07919e3d6c56 667 /**
andrewbonney 0:07919e3d6c56 668 Invoked as a callback from a child ctor when we pass in a parent pointer.
andrewbonney 0:07919e3d6c56 669 OR used from switchToNewSubParser, in which case it may be the 2nd time
andrewbonney 0:07919e3d6c56 670 we're called for a given child (see scenarios in expatppNesting class comment).
andrewbonney 0:07919e3d6c56 671 */
andrewbonney 0:07919e3d6c56 672 void
andrewbonney 0:07919e3d6c56 673 expatppNesting::AdoptChild(expatppNesting* adoptingChild)
andrewbonney 0:07919e3d6c56 674 {
andrewbonney 0:07919e3d6c56 675 if ( mOwnedChild != adoptingChild )
andrewbonney 0:07919e3d6c56 676 {
andrewbonney 0:07919e3d6c56 677 delete mOwnedChild;
andrewbonney 0:07919e3d6c56 678 mOwnedChild = adoptingChild;
andrewbonney 0:07919e3d6c56 679 }
andrewbonney 0:07919e3d6c56 680 }
andrewbonney 0:07919e3d6c56 681
andrewbonney 0:07919e3d6c56 682
andrewbonney 0:07919e3d6c56 683 /**
andrewbonney 0:07919e3d6c56 684 to use parent's underlying expat parser
andrewbonney 0:07919e3d6c56 685 */
andrewbonney 0:07919e3d6c56 686 void
andrewbonney 0:07919e3d6c56 687 expatppNesting::RegisterWithParentXMLParser()
andrewbonney 0:07919e3d6c56 688 {
andrewbonney 0:07919e3d6c56 689 mParser = mParent->mParser;
andrewbonney 0:07919e3d6c56 690 ::XML_SetUserData(mParser, this);
andrewbonney 0:07919e3d6c56 691 }
andrewbonney 0:07919e3d6c56 692
andrewbonney 0:07919e3d6c56 693
andrewbonney 0:07919e3d6c56 694 /**
andrewbonney 0:07919e3d6c56 695 User code (typically the startElement handler of user parsers derived from expatppNesting)
andrewbonney 0:07919e3d6c56 696 may call
andrewbonney 0:07919e3d6c56 697 switchToNewSubParser( new UserChildParser() );
andrewbonney 0:07919e3d6c56 698 to hand off the current document to a child parser that understands the next segment of XML.
andrewbonney 0:07919e3d6c56 699 Control will be returned to the original (parent) parser when the end of the child element
andrewbonney 0:07919e3d6c56 700 is reached.
andrewbonney 0:07919e3d6c56 701 In its lifetime a 'parent' parser may switch control to several child parsers (one at a time
andrewbonney 0:07919e3d6c56 702 of course) as it moves through the document encoutering various types of child element.
andrewbonney 0:07919e3d6c56 703
andrewbonney 0:07919e3d6c56 704 A child to which older code (eg: OOFILE) has just switched control by
andrewbonney 0:07919e3d6c56 705 new childParser(this) will be self-deleting and will clear our mOwnedChild in its dtor.
andrewbonney 0:07919e3d6c56 706 */
andrewbonney 0:07919e3d6c56 707 void expatppNesting::switchToNewSubParser( expatppNesting* pAdoptedChild )
andrewbonney 0:07919e3d6c56 708 {
andrewbonney 0:07919e3d6c56 709 assert(pAdoptedChild);
andrewbonney 0:07919e3d6c56 710 AdoptChild(pAdoptedChild);
andrewbonney 0:07919e3d6c56 711 pAdoptedChild->BeAdopted(this);
andrewbonney 0:07919e3d6c56 712 }
andrewbonney 0:07919e3d6c56 713
andrewbonney 0:07919e3d6c56 714
andrewbonney 0:07919e3d6c56 715 /**
andrewbonney 0:07919e3d6c56 716 If this is root parser, nestedEndElementCallback won't call returnToParent.
andrewbonney 0:07919e3d6c56 717 Therefore it is safe to put parsers on the stack.
andrewbonney 0:07919e3d6c56 718 */
andrewbonney 0:07919e3d6c56 719 expatppNesting*
andrewbonney 0:07919e3d6c56 720 expatppNesting::returnToParent()
andrewbonney 0:07919e3d6c56 721 {
andrewbonney 0:07919e3d6c56 722 expatppNesting* ret = mParent;
andrewbonney 0:07919e3d6c56 723 ::XML_SetUserData(mParser, mParent);
andrewbonney 0:07919e3d6c56 724 mParent=0;
andrewbonney 0:07919e3d6c56 725 mParser=0; // prevent parser shutdown by expatpp::~expatpp!!
andrewbonney 0:07919e3d6c56 726 if (mSelfDeleting) {
andrewbonney 0:07919e3d6c56 727 ret->OwnedChildOrphansItself(this);
andrewbonney 0:07919e3d6c56 728 delete this; // MUST BE LAST THING CALLED IN NON-VIRTUAL FUNCTION, NO MEMBER ACCESS
andrewbonney 0:07919e3d6c56 729 }
andrewbonney 0:07919e3d6c56 730 return ret;
andrewbonney 0:07919e3d6c56 731 }
andrewbonney 0:07919e3d6c56 732
andrewbonney 0:07919e3d6c56 733
andrewbonney 0:07919e3d6c56 734 void
andrewbonney 0:07919e3d6c56 735 expatppNesting::nestedStartElementCallback(void *userData, const XML_Char* name, const XML_Char** atts)
andrewbonney 0:07919e3d6c56 736 {
andrewbonney 0:07919e3d6c56 737 assert(userData);
andrewbonney 0:07919e3d6c56 738 expatppNesting* nestedParser = (expatppNesting*)userData;
andrewbonney 0:07919e3d6c56 739 nestedParser->mDepth++;
andrewbonney 0:07919e3d6c56 740 nestedParser->startElement(name, atts); // probably user override
andrewbonney 0:07919e3d6c56 741 }
andrewbonney 0:07919e3d6c56 742
andrewbonney 0:07919e3d6c56 743
andrewbonney 0:07919e3d6c56 744 /**
andrewbonney 0:07919e3d6c56 745 If this is root parser, will never hit nestedEndElementCallback after closing element,
andrewbonney 0:07919e3d6c56 746 except for when we call it.
andrewbonney 0:07919e3d6c56 747 \param userData should be non-nil except for specific case of ending root
andrewbonney 0:07919e3d6c56 748 */
andrewbonney 0:07919e3d6c56 749 void
andrewbonney 0:07919e3d6c56 750 expatppNesting::nestedEndElementCallback(void *userData, const XML_Char* name)
andrewbonney 0:07919e3d6c56 751 {
andrewbonney 0:07919e3d6c56 752 if (!userData)
andrewbonney 0:07919e3d6c56 753 return; // end tag for root
andrewbonney 0:07919e3d6c56 754
andrewbonney 0:07919e3d6c56 755 expatppNesting* nestedParser = (expatppNesting*)userData;
andrewbonney 0:07919e3d6c56 756 // we don't know until we hit a closing tag 'outside' us that our run is done
andrewbonney 0:07919e3d6c56 757 if (nestedParser->mDepth==0) {
andrewbonney 0:07919e3d6c56 758 expatppNesting* parentParser = nestedParser->returnToParent();
andrewbonney 0:07919e3d6c56 759 nestedEndElementCallback(parentParser, name); // callbacks for expatppNesting stay registered, so safe
andrewbonney 0:07919e3d6c56 760 //if we don't invoke their callback, they will not balance their mDepth
andrewbonney 0:07919e3d6c56 761 }
andrewbonney 0:07919e3d6c56 762 else {
andrewbonney 0:07919e3d6c56 763 // end of an element this parser has started - normal case
andrewbonney 0:07919e3d6c56 764 nestedParser->endElement(name); // probably user override
andrewbonney 0:07919e3d6c56 765 nestedParser->mDepth--;
andrewbonney 0:07919e3d6c56 766 }
andrewbonney 0:07919e3d6c56 767 }
andrewbonney 0:07919e3d6c56 768
andrewbonney 0:07919e3d6c56 769
andrewbonney 0:07919e3d6c56 770 /**
andrewbonney 0:07919e3d6c56 771 Called by switchToNewSubParser to indicate a newly created child parser
andrewbonney 0:07919e3d6c56 772 is now the currently active child for adoptingParent and the child
andrewbonney 0:07919e3d6c56 773 isn't expected to be self deleting.
andrewbonney 0:07919e3d6c56 774
andrewbonney 0:07919e3d6c56 775 Normal code to create an owned child would be either
andrewbonney 0:07919e3d6c56 776 switchToNewSubParser( new UserChildParser(this) );
andrewbonney 0:07919e3d6c56 777 where this is the currently active parser and you want to be deleting it, or
andrewbonney 0:07919e3d6c56 778 new UserChildParser(this);
andrewbonney 0:07919e3d6c56 779 to have a child parser self-delete
andrewbonney 0:07919e3d6c56 780
andrewbonney 0:07919e3d6c56 781 \par Important Safety Note
andrewbonney 0:07919e3d6c56 782 Copes with the situation of people forgetting to pass
andrewbonney 0:07919e3d6c56 783 in the parent parser (and hence creating a new one by default)
andrewbonney 0:07919e3d6c56 784 if invoked by switchToNewSubParser( new UserChildParser() )
andrewbonney 0:07919e3d6c56 785 by somewhat wastefully deleting the parser created in expatpp::expatpp
andrewbonney 0:07919e3d6c56 786 by us being a root parser.
andrewbonney 0:07919e3d6c56 787 */
andrewbonney 0:07919e3d6c56 788 void
andrewbonney 0:07919e3d6c56 789 expatppNesting::BeAdopted(expatppNesting* adoptingParent)
andrewbonney 0:07919e3d6c56 790 {
andrewbonney 0:07919e3d6c56 791 if (mParent) {
andrewbonney 0:07919e3d6c56 792 assert(mParent==adoptingParent);
andrewbonney 0:07919e3d6c56 793 }
andrewbonney 0:07919e3d6c56 794 else { // root parser being adopted, cleanup!
andrewbonney 0:07919e3d6c56 795 ReleaseParser();
andrewbonney 0:07919e3d6c56 796 mParent = adoptingParent;
andrewbonney 0:07919e3d6c56 797 RegisterWithParentXMLParser();
andrewbonney 0:07919e3d6c56 798 }
andrewbonney 0:07919e3d6c56 799 mSelfDeleting = false;
andrewbonney 0:07919e3d6c56 800 }
andrewbonney 0:07919e3d6c56 801
andrewbonney 0:07919e3d6c56 802
andrewbonney 0:07919e3d6c56 803
andrewbonney 0:07919e3d6c56 804