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 #if 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 PXMLElement * currentElement;
00094 PXMLData * lastElement;
00095 PString version, encoding;
00096 int standAlone;
00097 };
00098
00099 class PXMLObject;
00100 class PXMLElement;
00101 class PXMLData;
00102
00104
00105 class PXMLBase : public PObject
00106 {
00107 public:
00108 PXMLBase(int _options = -1)
00109 : options(_options) { if (options < 0) options = 0; }
00110
00111 void SetOptions(int _options)
00112 { options = _options; }
00113
00114 int GetOptions() const { return options; }
00115
00116 virtual PBoolean IsNoIndentElement(
00117 const PString &
00118 ) const
00119 {
00120 return PFalse;
00121 }
00122
00123 protected:
00124 int options;
00125 };
00126
00127
00128 class PXML : public PXMLBase
00129 {
00130 PCLASSINFO(PXML, PObject);
00131 public:
00132
00133 PXML(
00134 int options = -1,
00135 const char * noIndentElements = NULL
00136 );
00137 PXML(
00138 const PString & data,
00139 int options = -1,
00140 const char * noIndentElements = NULL
00141 );
00142
00143 PXML(const PXML & xml);
00144
00145 ~PXML();
00146
00147 PBoolean IsDirty() const;
00148
00149 PBoolean Load(const PString & data, int options = -1);
00150
00151 PBoolean StartAutoReloadURL(const PURL & url,
00152 const PTimeInterval & timeout,
00153 const PTimeInterval & refreshTime,
00154 int _options = -1);
00155 PBoolean StopAutoReloadURL();
00156 PString GetAutoReloadStatus() { PWaitAndSignal m(autoLoadMutex); PString str = autoLoadError; return str; }
00157 PBoolean AutoLoadURL();
00158 virtual void OnAutoLoad(PBoolean ok);
00159
00160 PBoolean LoadURL(const PURL & url);
00161 PBoolean LoadURL(const PURL & url, const PTimeInterval & timeout, int _options = -1);
00162 PBoolean LoadFile(const PFilePath & fn, int options = -1);
00163
00164 virtual void OnLoaded() { }
00165
00166 PBoolean Save(int options = -1);
00167 PBoolean Save(PString & data, int options = -1);
00168 PBoolean SaveFile(const PFilePath & fn, int options = -1);
00169
00170 void RemoveAll();
00171
00172 PBoolean IsNoIndentElement(
00173 const PString & elementName
00174 ) const;
00175
00176 void PrintOn(ostream & strm) const;
00177
00178 PXMLElement * GetElement(const PCaselessString & name, PINDEX idx = 0) const;
00179 PXMLElement * GetElement(PINDEX idx) const;
00180 PINDEX GetNumElements() const;
00181 PXMLElement * GetRootElement() const { return rootElement; }
00182 PXMLElement * SetRootElement(PXMLElement * p);
00183 PXMLElement * SetRootElement(const PString & documentType);
00184 PBoolean RemoveElement(PINDEX idx);
00185
00186 PCaselessString GetDocumentType() const;
00187
00188 PString GetErrorString() const { return errorString; }
00189 PINDEX GetErrorColumn() const { return errorCol; }
00190 PINDEX GetErrorLine() const { return errorLine; }
00191
00192 PString GetDocType() const { return docType; }
00193 void SetDocType(const PString & v) { docType = v; }
00194
00195 PMutex & GetMutex() { return rootMutex; }
00196
00197 PDECLARE_NOTIFIER(PTimer, PXML, AutoReloadTimeout);
00198 PDECLARE_NOTIFIER(PThread, PXML, AutoReloadThread);
00199
00200
00201 static PString CreateStartTag (const PString & text);
00202 static PString CreateEndTag (const PString & text);
00203 static PString CreateTagNoData (const PString & text);
00204 static PString CreateTag (const PString & text, const PString & data);
00205
00206 protected:
00207 void Construct(int options, const char * noIndentElements);
00208 PXMLElement * rootElement;
00209 PMutex rootMutex;
00210
00211 PBoolean loadFromFile;
00212 PFilePath loadFilename;
00213 PString version, encoding;
00214 int standAlone;
00215
00216 PTimer autoLoadTimer;
00217 PURL autoloadURL;
00218 PTimeInterval autoLoadWaitTime;
00219 PMutex autoLoadMutex;
00220 PString autoLoadError;
00221
00222 PString errorString;
00223 PINDEX errorCol;
00224 PINDEX errorLine;
00225
00226 PSortedStringList noIndentElements;
00227
00228 PString docType;
00229 };
00230
00232
00233 PARRAY(PXMLObjectArray, PXMLObject);
00234
00235 class PXMLObject : public PObject {
00236 PCLASSINFO(PXMLObject, PObject);
00237 public:
00238 PXMLObject(PXMLElement * _parent)
00239 : parent(_parent) { dirty = PFalse; }
00240
00241 PXMLElement * GetParent()
00242 { return parent; }
00243
00244 PXMLObject * GetNextObject();
00245
00246 void SetParent(PXMLElement * newParent)
00247 {
00248 PAssert(parent == NULL, "Cannot reparent PXMLElement");
00249 parent = newParent;
00250 }
00251
00252 virtual void Output(ostream & strm, const PXMLBase & xml, int indent) const = 0;
00253
00254 virtual PBoolean IsElement() const = 0;
00255
00256 void SetDirty();
00257 PBoolean IsDirty() const { return dirty; }
00258
00259 virtual PXMLObject * Clone(PXMLElement * parent) const = 0;
00260
00261 protected:
00262 PXMLElement * parent;
00263 PBoolean dirty;
00264 };
00265
00267
00268 class PXMLData : public PXMLObject {
00269 PCLASSINFO(PXMLData, PXMLObject);
00270 public:
00271 PXMLData(PXMLElement * _parent, const PString & data);
00272 PXMLData(PXMLElement * _parent, const char * data, int len);
00273
00274 PBoolean IsElement() const { return PFalse; }
00275
00276 void SetString(const PString & str, PBoolean dirty = PTrue);
00277
00278 PString GetString() const { return value; }
00279
00280 void Output(ostream & strm, const PXMLBase & xml, int indent) const;
00281
00282 PXMLObject * Clone(PXMLElement * parent) const;
00283
00284 protected:
00285 PString value;
00286 };
00287
00289
00290 class PXMLElement : public PXMLObject {
00291 PCLASSINFO(PXMLElement, PXMLObject);
00292 public:
00293 PXMLElement(PXMLElement * _parent, const char * name = NULL);
00294 PXMLElement(PXMLElement * _parent, const PString & name, const PString & data);
00295
00296 PBoolean IsElement() const { return PTrue; }
00297
00298 void PrintOn(ostream & strm) const;
00299 void Output(ostream & strm, const PXMLBase & xml, int indent) const;
00300
00301 PCaselessString GetName() const
00302 { return name; }
00303
00304 void SetName(const PString & v)
00305 { name = v; }
00306
00307 PINDEX GetSize() const
00308 { return subObjects.GetSize(); }
00309
00310 PXMLObject * AddSubObject(PXMLObject * elem, PBoolean dirty = PTrue);
00311
00312 PXMLElement * AddChild (PXMLElement * elem, PBoolean dirty = PTrue);
00313 PXMLData * AddChild (PXMLData * elem, PBoolean dirty = PTrue);
00314
00315 void SetAttribute(const PCaselessString & key,
00316 const PString & value,
00317 PBoolean setDirty = PTrue);
00318
00319 PString GetAttribute(const PCaselessString & key) const;
00320 PString GetKeyAttribute(PINDEX idx) const;
00321 PString GetDataAttribute(PINDEX idx) const;
00322 PBoolean HasAttribute(const PCaselessString & key);
00323 PBoolean HasAttributes() const { return attributes.GetSize() > 0; }
00324 PINDEX GetNumAttributes() const { return attributes.GetSize(); }
00325
00326 PXMLElement * GetElement(const PCaselessString & name, PINDEX idx = 0) const;
00327 PXMLObject * GetElement(PINDEX idx = 0) const;
00328 PBoolean RemoveElement(PINDEX idx);
00329
00330 PINDEX FindObject(PXMLObject * ptr) const;
00331
00332 PBoolean HasSubObjects() const
00333 { return subObjects.GetSize() != 0; }
00334
00335 PXMLObjectArray GetSubObjects() const
00336 { return subObjects; }
00337
00338 PString GetData() const;
00339
00340 PXMLObject * Clone(PXMLElement * parent) const;
00341
00342 protected:
00343 PCaselessString name;
00344 PStringToString attributes;
00345 PXMLObjectArray subObjects;
00346 PBoolean dirty;
00347 };
00348
00350
00351 class PConfig;
00352
00353 class PXMLSettings : public PXML
00354 {
00355 PCLASSINFO(PXMLSettings, PXML);
00356 public:
00357 PXMLSettings(int options = PXMLParser::NewLineAfterElement);
00358 PXMLSettings(const PString & data, int options = PXMLParser::NewLineAfterElement);
00359 PXMLSettings(const PConfig & data, int options = PXMLParser::NewLineAfterElement);
00360
00361 PBoolean Load(const PString & data);
00362 PBoolean LoadFile(const PFilePath & fn);
00363
00364 PBoolean Save();
00365 PBoolean Save(PString & data);
00366 PBoolean SaveFile(const PFilePath & fn);
00367
00368 void SetAttribute(const PCaselessString & section, const PString & key, const PString & value);
00369
00370 PString GetAttribute(const PCaselessString & section, const PString & key) const;
00371 PBoolean HasAttribute(const PCaselessString & section, const PString & key) const;
00372
00373 void ToConfig(PConfig & cfg) const;
00374 };
00375
00377
00378 class PXMLStreamParser : public PXMLParser
00379 {
00380 PCLASSINFO(PXMLStreamParser, PXMLParser);
00381 public:
00382 PXMLStreamParser();
00383
00384 virtual void EndElement(const char * name);
00385 virtual PXML * Read(PChannel * channel);
00386
00387 protected:
00388 PBoolean rootOpen;
00389 PQueue<PXML> messages;
00390 };
00391
00392 #endif // P_EXPAT
00393
00394 #endif