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