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 _PXML_H
00032 #define _PXML_H
00033
00034 #ifdef P_USE_PRAGMA
00035 #pragma interface
00036 #endif
00037
00038 #ifndef _PTLIB_H
00039 #include <ptlib.h>
00040 #endif
00041
00042 #include <ptbuildopts.h>
00043
00044 #ifdef P_EXPAT
00045
00046 #include <ptclib/http.h>
00047
00049
00050 class PXMLElement;
00051 class PXMLData;
00052
00053 class PXMLParser : public PObject
00054 {
00055 PCLASSINFO(PXMLParser, PObject);
00056 public:
00057 enum Options {
00058 Indent = 1,
00059 NewLineAfterElement = 2,
00060 NoIgnoreWhiteSpace = 4,
00061 CloseExtended = 8,
00062 WithNS = 16,
00063 };
00064
00065 PXMLParser(int options = -1);
00066 ~PXMLParser();
00067 PBoolean Parse(const char * data, int dataLen, PBoolean final);
00068 void GetErrorInfo(PString & errorString, PINDEX & errorCol, PINDEX & errorLine);
00069
00070 virtual void StartElement(const char * name, const char **attrs);
00071 virtual void EndElement(const char * name);
00072 virtual void AddCharacterData(const char * data, int len);
00073 virtual void XmlDecl(const char * version, const char * encoding, int standAlone);
00074 virtual void StartDocTypeDecl(const char * docTypeName,
00075 const char * sysid,
00076 const char * pubid,
00077 int hasInternalSubSet);
00078 virtual void EndDocTypeDecl();
00079 virtual void StartNamespaceDeclHandler(const char * prefix, const char * uri);
00080 virtual void EndNamespaceDeclHandler(const char * prefix);
00081
00082 PString GetVersion() const { return version; }
00083 PString GetEncoding() const { return encoding; }
00084 PBoolean GetStandAlone() const { return standAlone; }
00085
00086 PXMLElement * GetXMLTree() const;
00087 PXMLElement * SetXMLTree(PXMLElement * newRoot);
00088
00089 protected:
00090 int options;
00091 void * expat;
00092 PXMLElement * rootElement;
00093 bool rootOpen;
00094 PXMLElement * currentElement;
00095 PXMLData * lastElement;
00096 PString version, encoding;
00097 int standAlone;
00098 };
00099
00100 class PXMLObject;
00101 class PXMLElement;
00102 class PXMLData;
00103
00105
00106 class PXMLBase : public PObject
00107 {
00108 public:
00109 PXMLBase(int _options = -1)
00110 : options(_options) { if (options < 0) options = 0; }
00111
00112 void SetOptions(int _options)
00113 { options = _options; }
00114
00115 int GetOptions() const { return options; }
00116
00117 virtual PBoolean IsNoIndentElement(
00118 const PString &
00119 ) const
00120 {
00121 return PFalse;
00122 }
00123
00124 protected:
00125 int options;
00126 };
00127
00128
00129 class PXML : public PXMLBase
00130 {
00131 PCLASSINFO(PXML, PObject);
00132 public:
00133
00134 PXML(
00135 int options = -1,
00136 const char * noIndentElements = NULL
00137 );
00138 PXML(
00139 const PString & data,
00140 int options = -1,
00141 const char * noIndentElements = NULL
00142 );
00143
00144 PXML(const PXML & xml);
00145
00146 ~PXML();
00147
00148 bool IsLoaded() const { return rootElement != NULL; }
00149 PBoolean IsDirty() const;
00150
00151 PBoolean Load(const PString & data, int options = -1);
00152
00153 #if P_HTTP
00154 PBoolean StartAutoReloadURL(const PURL & url,
00155 const PTimeInterval & timeout,
00156 const PTimeInterval & refreshTime,
00157 int _options = -1);
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 * _parent)
00249 : parent(_parent) { dirty = PFalse; }
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);
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