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 #ifndef P_EXPAT
00043
00044 namespace PXML {
00045 extern PString EscapeSpecialChars(const PString & str);
00046 };
00047
00048 #else
00049
00050 #include <ptclib/http.h>
00051
00053
00054 class PXMLElement;
00055 class PXMLData;
00056
00057
00058 class PXMLObject;
00059 class PXMLElement;
00060 class PXMLData;
00061
00063
00064 class PXMLBase : public PObject
00065 {
00066 public:
00067 enum {
00068 DEFAULT_MAX_ENTITY_LENGTH = 4096
00069 };
00070
00071 enum Options {
00072 NoOptions = 0x0000,
00073 Indent = 0x0001,
00074 NewLineAfterElement = 0x0002,
00075 NoIgnoreWhiteSpace = 0x0004,
00076 CloseExtended = 0x0008,
00077 WithNS = 0x0010,
00078 FragmentOnly = 0x0020,
00079 AllOptions = 0xffff
00080 };
00081 __inline friend Options operator|(Options o1, Options o2) { return (Options)(((unsigned)o1) | ((unsigned)o2)); }
00082 __inline friend Options operator&(Options o1, Options o2) { return (Options)(((unsigned)o1) & ((unsigned)o2)); }
00083
00084 enum StandAloneType {
00085 UninitialisedStandAlone = -2,
00086 UnknownStandAlone = -1,
00087 NotStandAlone,
00088 IsStandAlone
00089 };
00090
00091 PXMLBase(int opts = NoOptions);
00092
00093 void SetOptions(int opts)
00094 { m_options = opts; }
00095
00096 int GetOptions() const { return m_options; }
00097
00098 virtual PBoolean IsNoIndentElement(
00099 const PString &
00100 ) const
00101 {
00102 return false;
00103 }
00104
00105 void SetMaxEntityLength(unsigned len) { m_maxEntityLength = len; }
00106 unsigned GetMaxEntityLength() const { return m_maxEntityLength; }
00107
00108 protected:
00109 int m_options;
00110 unsigned m_maxEntityLength;
00111 };
00112
00113
00114 class PXML : public PXMLBase
00115 {
00116 PCLASSINFO(PXML, PObject);
00117 public:
00118 PXML(
00119 int options = NoOptions,
00120 const char * noIndentElements = NULL
00121 );
00122 PXML(
00123 const PString & data,
00124 int options = NoOptions,
00125 const char * noIndentElements = NULL
00126 );
00127
00128 PXML(const PXML & xml);
00129
00130 ~PXML();
00131
00132 bool IsLoaded() const { return rootElement != NULL; }
00133 bool IsDirty() const;
00134
00135 bool Load(const PString & data, Options options = NoOptions);
00136 bool LoadFile(const PFilePath & fn, Options options = NoOptions);
00137
00138 virtual void OnLoaded() { }
00139
00140 bool Save(Options options = NoOptions);
00141 bool Save(PString & data, Options options = NoOptions);
00142 bool SaveFile(const PFilePath & fn, Options options = NoOptions);
00143
00144 void RemoveAll();
00145
00146 PBoolean IsNoIndentElement(
00147 const PString & elementName
00148 ) const;
00149
00150 PString AsString() const;
00151 void PrintOn(ostream & strm) const;
00152 void ReadFrom(istream & strm);
00153
00154
00155 PXMLElement * GetElement(const PCaselessString & name, const PCaselessString & attr, const PString & attrval) const;
00156 PXMLElement * GetElement(const PCaselessString & name, PINDEX idx = 0) const;
00157 PXMLElement * GetElement(PINDEX idx) const;
00158 PINDEX GetNumElements() const;
00159 PXMLElement * GetRootElement() const { return rootElement; }
00160 PXMLElement * SetRootElement(PXMLElement * p);
00161 PXMLElement * SetRootElement(const PString & documentType);
00162 bool RemoveElement(PINDEX idx);
00163
00164 PCaselessString GetDocumentType() const;
00165
00166
00167 enum ValidationOp {
00168 EndOfValidationList,
00169 DocType,
00170 ElementName,
00171 RequiredAttribute,
00172 RequiredNonEmptyAttribute,
00173 RequiredAttributeWithValue,
00174 RequiredElement,
00175 Subtree,
00176 RequiredAttributeWithValueMatching,
00177 RequiredElementWithBodyMatching,
00178 OptionalElement,
00179 OptionalAttribute,
00180 OptionalNonEmptyAttribute,
00181 OptionalAttributeWithValue,
00182 OptionalAttributeWithValueMatching,
00183 OptionalElementWithBodyMatching,
00184 SetDefaultNamespace,
00185 SetNamespace,
00186
00187 RequiredAttributeWithValueMatchingEx = RequiredAttributeWithValueMatching + 0x8000,
00188 OptionalAttributeWithValueMatchingEx = OptionalAttributeWithValueMatching + 0x8000,
00189 RequiredElementWithBodyMatchingEx = RequiredElementWithBodyMatching + 0x8000,
00190 OptionalElementWithBodyMatchingEx = OptionalElementWithBodyMatching + 0x8000
00191 };
00192
00193 struct ValidationContext {
00194 PString m_defaultNameSpace;
00195 PStringToString m_nameSpaces;
00196 };
00197
00198 struct ValidationInfo {
00199 ValidationOp m_op;
00200 const char * m_name;
00201
00202 union {
00203 const void * m_placeHolder;
00204 const char * m_attributeValues;
00205 ValidationInfo * m_subElement;
00206 const char * m_namespace;
00207 };
00208
00209 PINDEX m_minCount;
00210 PINDEX m_maxCount;
00211 };
00212
00213 bool Validate(const ValidationInfo * validator);
00214 bool ValidateElements(ValidationContext & context, PXMLElement * baseElement, const ValidationInfo * elements);
00215 bool ValidateElement(ValidationContext & context, PXMLElement * element, const ValidationInfo * elements);
00216 bool LoadAndValidate(const PString & body, const PXML::ValidationInfo * validator, PString & error, int options = NoOptions);
00217
00218 PString GetErrorString() const { return m_errorString; }
00219 unsigned GetErrorColumn() const { return m_errorColumn; }
00220 unsigned GetErrorLine() const { return m_errorLine; }
00221
00222 PString GetDocType() const { return docType; }
00223 void SetDocType(const PString & v) { docType = v; }
00224
00225 PMutex & GetMutex() { return rootMutex; }
00226
00227
00228 static PString CreateStartTag (const PString & text);
00229 static PString CreateEndTag (const PString & text);
00230 static PString CreateTagNoData (const PString & text);
00231 static PString CreateTag (const PString & text, const PString & data);
00232
00233 static PString EscapeSpecialChars(const PString & string);
00234
00235 protected:
00236 void Construct(int options, const char * noIndentElements);
00237 PXMLElement * rootElement;
00238 PMutex rootMutex;
00239
00240 bool loadFromFile;
00241 PFilePath loadFilename;
00242 PString version, encoding;
00243 StandAloneType m_standAlone;
00244
00245 PStringStream m_errorString;
00246 unsigned m_errorLine;
00247 unsigned m_errorColumn;
00248
00249 PSortedStringList noIndentElements;
00250
00251 PString docType;
00252 PString m_defaultNameSpace;
00253 };
00254
00255
00256 #if P_HTTP
00257 class PXML_HTTP : public PXML
00258 {
00259 PCLASSINFO(PXML_HTTP, PXML);
00260 public:
00261 PXML_HTTP(
00262 int options = NoOptions,
00263 const char * noIndentElements = NULL
00264 );
00265
00266 bool StartAutoReloadURL(
00267 const PURL & url,
00268 const PTimeInterval & timeout,
00269 const PTimeInterval & refreshTime,
00270 Options options = NoOptions
00271 );
00272 bool StopAutoReloadURL();
00273 PString GetAutoReloadStatus() { PWaitAndSignal m(autoLoadMutex); PString str = autoLoadError; return str; }
00274 bool AutoLoadURL();
00275 virtual void OnAutoLoad(PBoolean ok);
00276
00277 bool LoadURL(const PURL & url);
00278 bool LoadURL(const PURL & url, const PTimeInterval & timeout, Options options = NoOptions);
00279
00280 protected:
00281 PDECLARE_NOTIFIER(PTimer, PXML_HTTP, AutoReloadTimeout);
00282 PDECLARE_NOTIFIER(PThread, PXML_HTTP, AutoReloadThread);
00283
00284 PTimer autoLoadTimer;
00285 PURL autoloadURL;
00286 PTimeInterval autoLoadWaitTime;
00287 PMutex autoLoadMutex;
00288 PString autoLoadError;
00289 };
00290 #endif // P_HTTP
00291
00293
00294 PARRAY(PXMLObjectArray, PXMLObject);
00295
00296 class PXMLObject : public PObject {
00297 PCLASSINFO(PXMLObject, PObject);
00298 public:
00299 PXMLObject(PXMLElement * par)
00300 : parent(par) { dirty = false; }
00301
00302 PXMLElement * GetParent() const
00303 { return parent; }
00304
00305 PXMLObject * GetNextObject() const;
00306
00307 void SetParent(PXMLElement * newParent)
00308 {
00309 PAssert(parent == NULL, "Cannot reparent PXMLElement");
00310 parent = newParent;
00311 }
00312
00313 PString AsString() const;
00314
00315 virtual void Output(ostream & strm, const PXMLBase & xml, int indent) const = 0;
00316
00317 virtual PBoolean IsElement() const = 0;
00318
00319 void SetDirty();
00320 bool IsDirty() const { return dirty; }
00321
00322 virtual PXMLObject * Clone(PXMLElement * parent) const = 0;
00323
00324 protected:
00325 PXMLElement * parent;
00326 bool dirty;
00327 };
00328
00330
00331 class PXMLData : public PXMLObject {
00332 PCLASSINFO(PXMLData, PXMLObject);
00333 public:
00334 PXMLData(PXMLElement * parent, const PString & data);
00335 PXMLData(PXMLElement * parent, const char * data, int len);
00336
00337 PBoolean IsElement() const { return false; }
00338
00339 void SetString(const PString & str, bool dirty = true);
00340
00341 PString GetString() const { return value; }
00342
00343 void Output(ostream & strm, const PXMLBase & xml, int indent) const;
00344
00345 PXMLObject * Clone(PXMLElement * parent) const;
00346
00347 protected:
00348 PString value;
00349 };
00350
00352
00353 class PXMLElement : public PXMLObject {
00354 PCLASSINFO(PXMLElement, PXMLObject);
00355 public:
00356 PXMLElement(PXMLElement * parent, const char * name = NULL);
00357 PXMLElement(PXMLElement * parent, const PString & name, const PString & data);
00358
00359 PBoolean IsElement() const { return true; }
00360
00361 void PrintOn(ostream & strm) const;
00362 void Output(ostream & strm, const PXMLBase & xml, int indent) const;
00363
00364 PCaselessString GetName() const
00365 { return name; }
00366
00371 PCaselessString GetPathName() const;
00372
00373 void SetName(const PString & v)
00374 { name = v; }
00375
00376 PINDEX GetSize() const
00377 { return subObjects.GetSize(); }
00378
00379 PXMLObject * AddSubObject(PXMLObject * elem, bool dirty = true);
00380
00381 PXMLElement * AddChild (PXMLElement * elem, bool dirty = true);
00382 PXMLData * AddChild (PXMLData * elem, bool dirty = true);
00383
00384 PXMLElement * AddElement(const char * name);
00385 PXMLElement * AddElement(const PString & name, const PString & data);
00386 PXMLElement * AddElement(const PString & name, const PString & attrName, const PString & attrVal);
00387
00388 void SetAttribute(const PCaselessString & key,
00389 const PString & value,
00390 bool setDirty = true);
00391
00392 PString GetAttribute(const PCaselessString & key) const;
00393 PString GetKeyAttribute(PINDEX idx) const;
00394 PString GetDataAttribute(PINDEX idx) const;
00395 bool HasAttribute(const PCaselessString & key) const;
00396 bool HasAttributes() const { return attributes.GetSize() > 0; }
00397 PINDEX GetNumAttributes() const { return attributes.GetSize(); }
00398
00399 PXMLElement * GetElement(const PCaselessString & name, const PCaselessString & attr, const PString & attrval) const;
00400 PXMLElement * GetElement(const PCaselessString & name, PINDEX idx = 0) const;
00401 PXMLObject * GetElement(PINDEX idx = 0) const;
00402 bool RemoveElement(PINDEX idx);
00403
00404 PINDEX FindObject(const PXMLObject * ptr) const;
00405
00406 bool HasSubObjects() const
00407 { return subObjects.GetSize() != 0; }
00408
00409 PXMLObjectArray GetSubObjects() const
00410 { return subObjects; }
00411
00412 PXMLObject * GetSubObject(PINDEX idx = 0) const
00413 { return GetElement(idx); }
00414
00415 PString GetData() const;
00416 void SetData(const PString & data);
00417 void AddData(const PString & data);
00418
00419 PXMLObject * Clone(PXMLElement * parent) const;
00420
00421 void GetFilePosition(unsigned & col, unsigned & line) const { col = column; line = lineNumber; }
00422 void SetFilePosition(unsigned col, unsigned line) { column = col; lineNumber = line; }
00423
00424 void AddNamespace(const PString & prefix, const PString & uri);
00425 void RemoveNamespace(const PString & prefix);
00426
00427 bool GetDefaultNamespace(PCaselessString & str) const;
00428 bool GetNamespace(const PCaselessString & prefix, PCaselessString & str) const;
00429 PCaselessString PrependNamespace(const PCaselessString & name) const;
00430 bool GetURIForNamespace(const PCaselessString & prefix, PCaselessString & uri);
00431
00432 protected:
00433 PCaselessString name;
00434 PStringToString attributes;
00435 PXMLObjectArray subObjects;
00436 bool dirty;
00437 unsigned column;
00438 unsigned lineNumber;
00439 PStringToString m_nameSpaces;
00440 PCaselessString m_defaultNamespace;
00441 };
00442
00444
00445 class PConfig;
00446
00447 class PXMLSettings : public PXML
00448 {
00449 PCLASSINFO(PXMLSettings, PXML);
00450 public:
00451 PXMLSettings(Options options = NewLineAfterElement);
00452 PXMLSettings(const PString & data, Options options = NewLineAfterElement);
00453 PXMLSettings(const PConfig & data, Options options = NewLineAfterElement);
00454
00455 bool Load(const PString & data);
00456 bool LoadFile(const PFilePath & fn);
00457
00458 bool Save();
00459 bool Save(PString & data);
00460 bool SaveFile(const PFilePath & fn);
00461
00462 void SetAttribute(const PCaselessString & section, const PString & key, const PString & value);
00463
00464 PString GetAttribute(const PCaselessString & section, const PString & key) const;
00465 bool HasAttribute(const PCaselessString & section, const PString & key) const;
00466
00467 void ToConfig(PConfig & cfg) const;
00468 };
00469
00470
00472
00473 class PXMLParser : public PXMLBase
00474 {
00475 PCLASSINFO(PXMLParser, PXMLBase);
00476 public:
00477 PXMLParser(int options = NoOptions);
00478 ~PXMLParser();
00479 bool Parse(const char * data, int dataLen, bool final);
00480 void GetErrorInfo(PString & errorString, unsigned & errorCol, unsigned & errorLine);
00481
00482 virtual void StartElement(const char * name, const char **attrs);
00483 virtual void EndElement(const char * name);
00484 virtual void AddCharacterData(const char * data, int len);
00485 virtual void XmlDecl(const char * version, const char * encoding, int standAlone);
00486 virtual void StartDocTypeDecl(const char * docTypeName,
00487 const char * sysid,
00488 const char * pubid,
00489 int hasInternalSubSet);
00490 virtual void EndDocTypeDecl();
00491 virtual void StartNamespaceDeclHandler(const char * prefix, const char * uri);
00492 virtual void EndNamespaceDeclHandler(const char * prefix);
00493
00494 PString GetVersion() const { return version; }
00495 PString GetEncoding() const { return encoding; }
00496
00497 StandAloneType GetStandAlone() const { return m_standAlone; }
00498
00499 PXMLElement * GetXMLTree() const;
00500 PXMLElement * SetXMLTree(PXMLElement * newRoot);
00501
00502 protected:
00503 void * expat;
00504 PXMLElement * rootElement;
00505 bool rootOpen;
00506 PXMLElement * currentElement;
00507 PXMLData * lastElement;
00508 PString version, encoding;
00509 StandAloneType m_standAlone;
00510 PStringToString m_tempNamespaceList;
00511 };
00512
00514
00515 class PXMLStreamParser : public PXMLParser
00516 {
00517 PCLASSINFO(PXMLStreamParser, PXMLParser);
00518 public:
00519 PXMLStreamParser();
00520
00521 virtual void EndElement(const char * name);
00522 virtual PXML * Read(PChannel * channel);
00523
00524 protected:
00525 PQueue<PXML> messages;
00526 };
00527
00528
00529 #endif // P_EXPAT
00530
00531 #endif // PTLIB_PXML_H
00532
00533
00534