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