00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #ifndef PTLIB_PXML_H
00032 #define PTLIB_PXML_H
00033
00034 #ifdef P_USE_PRAGMA
00035 #pragma interface
00036 #endif
00037
00038 #include <ptlib.h>
00039
00040 #include <ptbuildopts.h>
00041
00042 #ifdef P_EXPAT
00043
00044 #include <ptclib/http.h>
00045
00047
00048 class PXMLElement;
00049 class PXMLData;
00050
00051 class PXMLParser : public PObject
00052 {
00053 PCLASSINFO(PXMLParser, PObject);
00054 public:
00055 enum Options {
00056 Indent = 1,
00057 NewLineAfterElement = 2,
00058 NoIgnoreWhiteSpace = 4,
00059 CloseExtended = 8,
00060 WithNS = 16,
00061 };
00062
00063 PXMLParser(int options = -1);
00064 ~PXMLParser();
00065 PBoolean Parse(const char * data, int dataLen, PBoolean final);
00066 void GetErrorInfo(PString & errorString, PINDEX & errorCol, PINDEX & errorLine);
00067
00068 virtual void StartElement(const char * name, const char **attrs);
00069 virtual void EndElement(const char * name);
00070 virtual void AddCharacterData(const char * data, int len);
00071 virtual void XmlDecl(const char * version, const char * encoding, int standAlone);
00072 virtual void StartDocTypeDecl(const char * docTypeName,
00073 const char * sysid,
00074 const char * pubid,
00075 int hasInternalSubSet);
00076 virtual void EndDocTypeDecl();
00077 virtual void StartNamespaceDeclHandler(const char * prefix, const char * uri);
00078 virtual void EndNamespaceDeclHandler(const char * prefix);
00079
00080 PString GetVersion() const { return version; }
00081 PString GetEncoding() const { return encoding; }
00082 PBoolean GetStandAlone() const { return standAlone; }
00083
00084 PXMLElement * GetXMLTree() const;
00085 PXMLElement * SetXMLTree(PXMLElement * newRoot);
00086
00087 protected:
00088 int options;
00089 void * expat;
00090 PXMLElement * rootElement;
00091 bool rootOpen;
00092 PXMLElement * currentElement;
00093 PXMLData * lastElement;
00094 PString version, encoding;
00095 int standAlone;
00096 };
00097
00098 class PXMLObject;
00099 class PXMLElement;
00100 class PXMLData;
00101
00103
00104 class PXMLBase : public PObject
00105 {
00106 public:
00107 PXMLBase(int opts = -1)
00108 : options(opts) { if (options < 0) options = 0; }
00109
00110 void SetOptions(int opts)
00111 { options = opts; }
00112
00113 int GetOptions() const { return options; }
00114
00115 virtual PBoolean IsNoIndentElement(
00116 const PString &
00117 ) const
00118 {
00119 return PFalse;
00120 }
00121
00122 protected:
00123 int options;
00124 };
00125
00126
00127 class PXML : public PXMLBase
00128 {
00129 PCLASSINFO(PXML, PObject);
00130 public:
00131
00132 PXML(
00133 int options = -1,
00134 const char * noIndentElements = NULL
00135 );
00136 PXML(
00137 const PString & data,
00138 int options = -1,
00139 const char * noIndentElements = NULL
00140 );
00141
00142 PXML(const PXML & xml);
00143
00144 ~PXML();
00145
00146 bool IsLoaded() const { return rootElement != NULL; }
00147 PBoolean IsDirty() const;
00148
00149 PBoolean Load(const PString & data, int options = -1);
00150
00151 #if P_HTTP
00152 PBoolean StartAutoReloadURL(
00153 const PURL & url,
00154 const PTimeInterval & timeout,
00155 const PTimeInterval & refreshTime,
00156 int options = -1
00157 );
00158 PBoolean StopAutoReloadURL();
00159 PString GetAutoReloadStatus() { PWaitAndSignal m(autoLoadMutex); PString str = autoLoadError; return str; }
00160 PBoolean AutoLoadURL();
00161 virtual void OnAutoLoad(PBoolean ok);
00162
00163 PBoolean LoadURL(const PURL & url);
00164 PBoolean LoadURL(const PURL & url, const PTimeInterval & timeout, int options = -1);
00165 #endif // P_HTTP
00166
00167 PBoolean LoadFile(const PFilePath & fn, int options = -1);
00168
00169 virtual void OnLoaded() { }
00170
00171 PBoolean Save(int options = -1);
00172 PBoolean Save(PString & data, int options = -1);
00173 PBoolean SaveFile(const PFilePath & fn, int options = -1);
00174
00175 void RemoveAll();
00176
00177 PBoolean IsNoIndentElement(
00178 const PString & elementName
00179 ) const;
00180
00181 void PrintOn(ostream & strm) const;
00182 void ReadFrom(istream & strm);
00183
00184 PXMLElement * GetElement(const PCaselessString & name, PINDEX idx = 0) const;
00185 PXMLElement * GetElement(PINDEX idx) const;
00186 PINDEX GetNumElements() const;
00187 PXMLElement * GetRootElement() const { return rootElement; }
00188 PXMLElement * SetRootElement(PXMLElement * p);
00189 PXMLElement * SetRootElement(const PString & documentType);
00190 PBoolean RemoveElement(PINDEX idx);
00191
00192 PCaselessString GetDocumentType() const;
00193
00194 PString GetErrorString() const { return errorString; }
00195 PINDEX GetErrorColumn() const { return errorCol; }
00196 PINDEX GetErrorLine() const { return errorLine; }
00197
00198 PString GetDocType() const { return docType; }
00199 void SetDocType(const PString & v) { docType = v; }
00200
00201 PMutex & GetMutex() { return rootMutex; }
00202
00203 #if P_HTTP
00204 PDECLARE_NOTIFIER(PTimer, PXML, AutoReloadTimeout);
00205 PDECLARE_NOTIFIER(PThread, PXML, AutoReloadThread);
00206 #endif // P_HTTP
00207
00208
00209 static PString CreateStartTag (const PString & text);
00210 static PString CreateEndTag (const PString & text);
00211 static PString CreateTagNoData (const PString & text);
00212 static PString CreateTag (const PString & text, const PString & data);
00213
00214 protected:
00215 void Construct(int options, const char * noIndentElements);
00216 PXMLElement * rootElement;
00217 PMutex rootMutex;
00218
00219 PBoolean loadFromFile;
00220 PFilePath loadFilename;
00221 PString version, encoding;
00222 int standAlone;
00223
00224 #if P_HTTP
00225 PTimer autoLoadTimer;
00226 PURL autoloadURL;
00227 PTimeInterval autoLoadWaitTime;
00228 PMutex autoLoadMutex;
00229 PString autoLoadError;
00230 #endif // P_HTTP
00231
00232 PString errorString;
00233 PINDEX errorCol;
00234 PINDEX errorLine;
00235
00236 PSortedStringList noIndentElements;
00237
00238 PString docType;
00239 };
00240
00242
00243 PARRAY(PXMLObjectArray, PXMLObject);
00244
00245 class PXMLObject : public PObject {
00246 PCLASSINFO(PXMLObject, PObject);
00247 public:
00248 PXMLObject(PXMLElement * par)
00249 : parent(par) { dirty = false; }
00250
00251 PXMLElement * GetParent() const
00252 { return parent; }
00253
00254 PXMLObject * GetNextObject() const;
00255
00256 void SetParent(PXMLElement * newParent)
00257 {
00258 PAssert(parent == NULL, "Cannot reparent PXMLElement");
00259 parent = newParent;
00260 }
00261
00262 virtual void Output(ostream & strm, const PXMLBase & xml, int indent) const = 0;
00263
00264 virtual PBoolean IsElement() const = 0;
00265
00266 void SetDirty();
00267 PBoolean IsDirty() const { return dirty; }
00268
00269 virtual PXMLObject * Clone(PXMLElement * parent) const = 0;
00270
00271 protected:
00272 PXMLElement * parent;
00273 PBoolean dirty;
00274 };
00275
00277
00278 class PXMLData : public PXMLObject {
00279 PCLASSINFO(PXMLData, PXMLObject);
00280 public:
00281 PXMLData(PXMLElement * parent, const PString & data);
00282 PXMLData(PXMLElement * parent, const char * data, int len);
00283
00284 PBoolean IsElement() const { return PFalse; }
00285
00286 void SetString(const PString & str, PBoolean dirty = PTrue);
00287
00288 PString GetString() const { return value; }
00289
00290 void Output(ostream & strm, const PXMLBase & xml, int indent) const;
00291
00292 PXMLObject * Clone(PXMLElement * parent) const;
00293
00294 protected:
00295 PString value;
00296 };
00297
00299
00300 class PXMLElement : public PXMLObject {
00301 PCLASSINFO(PXMLElement, PXMLObject);
00302 public:
00303 PXMLElement(PXMLElement * parent, const char * name = NULL);
00304 PXMLElement(PXMLElement * parent, const PString & name, const PString & data);
00305
00306 PBoolean IsElement() const { return PTrue; }
00307
00308 void PrintOn(ostream & strm) const;
00309 void Output(ostream & strm, const PXMLBase & xml, int indent) const;
00310
00311 PCaselessString GetName() const
00312 { return name; }
00313
00318 PCaselessString GetPathName() const;
00319
00320 void SetName(const PString & v)
00321 { name = v; }
00322
00323 PINDEX GetSize() const
00324 { return subObjects.GetSize(); }
00325
00326 PXMLObject * AddSubObject(PXMLObject * elem, PBoolean dirty = PTrue);
00327
00328 PXMLElement * AddChild (PXMLElement * elem, PBoolean dirty = PTrue);
00329 PXMLData * AddChild (PXMLData * elem, PBoolean dirty = PTrue);
00330
00331 void SetAttribute(const PCaselessString & key,
00332 const PString & value,
00333 PBoolean setDirty = PTrue);
00334
00335 PString GetAttribute(const PCaselessString & key) const;
00336 PString GetKeyAttribute(PINDEX idx) const;
00337 PString GetDataAttribute(PINDEX idx) const;
00338 PBoolean HasAttribute(const PCaselessString & key) const;
00339 PBoolean HasAttributes() const { return attributes.GetSize() > 0; }
00340 PINDEX GetNumAttributes() const { return attributes.GetSize(); }
00341
00342 PXMLElement * GetElement(const PCaselessString & name, PINDEX idx = 0) const;
00343 PXMLObject * GetElement(PINDEX idx = 0) const;
00344 PBoolean RemoveElement(PINDEX idx);
00345
00346 PINDEX FindObject(const PXMLObject * ptr) const;
00347
00348 PBoolean HasSubObjects() const
00349 { return subObjects.GetSize() != 0; }
00350
00351 PXMLObjectArray GetSubObjects() const
00352 { return subObjects; }
00353
00354 PString GetData() const;
00355
00356 PXMLObject * Clone(PXMLElement * parent) const;
00357
00358 void GetFilePosition(unsigned & col, unsigned & line) const { col = column; line = lineNumber; }
00359 void SetFilePosition(unsigned col, unsigned line) { column = col; lineNumber = line; }
00360
00361 protected:
00362 PCaselessString name;
00363 PStringToString attributes;
00364 PXMLObjectArray subObjects;
00365 PBoolean dirty;
00366 unsigned column;
00367 unsigned lineNumber;
00368 };
00369
00371
00372 class PConfig;
00373
00374 class PXMLSettings : public PXML
00375 {
00376 PCLASSINFO(PXMLSettings, PXML);
00377 public:
00378 PXMLSettings(int options = PXMLParser::NewLineAfterElement);
00379 PXMLSettings(const PString & data, int options = PXMLParser::NewLineAfterElement);
00380 PXMLSettings(const PConfig & data, int options = PXMLParser::NewLineAfterElement);
00381
00382 PBoolean Load(const PString & data);
00383 PBoolean LoadFile(const PFilePath & fn);
00384
00385 PBoolean Save();
00386 PBoolean Save(PString & data);
00387 PBoolean SaveFile(const PFilePath & fn);
00388
00389 void SetAttribute(const PCaselessString & section, const PString & key, const PString & value);
00390
00391 PString GetAttribute(const PCaselessString & section, const PString & key) const;
00392 PBoolean HasAttribute(const PCaselessString & section, const PString & key) const;
00393
00394 void ToConfig(PConfig & cfg) const;
00395 };
00396
00398
00399 class PXMLStreamParser : public PXMLParser
00400 {
00401 PCLASSINFO(PXMLStreamParser, PXMLParser);
00402 public:
00403 PXMLStreamParser();
00404
00405 virtual void EndElement(const char * name);
00406 virtual PXML * Read(PChannel * channel);
00407
00408 protected:
00409 PQueue<PXML> messages;
00410 };
00411
00412 #endif // P_EXPAT
00413
00414 #endif // PTLIB_PXML_H
00415
00416
00417