PWLib
1.10.10
|
00001 /* 00002 * pxml.h 00003 * 00004 * XML parser support 00005 * 00006 * Portable Windows Library 00007 * 00008 * Copyright (c) 2002 Equivalence Pty. Ltd. 00009 * 00010 * The contents of this file are subject to the Mozilla Public License 00011 * Version 1.0 (the "License"); you may not use this file except in 00012 * compliance with the License. You may obtain a copy of the License at 00013 * http://www.mozilla.org/MPL/ 00014 * 00015 * Software distributed under the License is distributed on an "AS IS" 00016 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 00017 * the License for the specific language governing rights and limitations 00018 * under the License. 00019 * 00020 * The Original Code is Portable Windows Library. 00021 * 00022 * The Initial Developer of the Original Code is Equivalence Pty. Ltd. 00023 * 00024 * Contributor(s): ______________________________________. 00025 * 00026 * $Log: pxml.h,v $ 00027 * Revision 1.26 2005/11/30 12:47:37 csoutheren 00028 * Removed tabs, reformatted some code, and changed tags for Doxygen 00029 * 00030 * Revision 1.25 2005/08/04 20:10:24 csoutheren 00031 * Apply patch #1217596 00032 * Fixed problems with MacOSX Tiger 00033 * Thanks to Hannes Friederich 00034 * 00035 * Revision 1.24 2004/10/12 23:28:07 csoutheren 00036 * Fixed problem with bogus DOCTYPE being output 00037 * 00038 * Revision 1.23 2004/04/21 00:35:02 csoutheren 00039 * Added a stream parser for protocols like XMPP where each child of the root is to be considered a separate document/message. 00040 * Thanks to Federico Pinna and Reitek S.p.A. 00041 * 00042 * Revision 1.22 2003/04/27 23:54:13 craigs 00043 * Removed deprecated options 00044 * 00045 * Revision 1.21 2003/03/31 07:41:50 craigs 00046 * Fixed problem with accidental introduced dependency on expat.h 00047 * 00048 * Revision 1.20 2003/03/31 06:21:19 craigs 00049 * Split the expat wrapper from the XML file handling to allow reuse of the parser 00050 * 00051 * Revision 1.19 2003/01/13 02:14:02 robertj 00052 * Improved error logging for auto-loaded XML 00053 * 00054 * Revision 1.18 2002/12/16 06:38:24 robertj 00055 * Added ability to specify certain elemets (by name) that are exempt from 00056 * the indent formatting. Useful for XML/RPC where leading white space is 00057 * not ignored by all servers. 00058 * 00059 * Revision 1.17 2002/11/26 05:53:57 craigs 00060 * Added ability to auto-reload from URL 00061 * 00062 * Revision 1.16 2002/11/21 08:09:04 craigs 00063 * Changed to not overwrite XML data if load fails 00064 * 00065 * Revision 1.15 2002/11/19 07:37:38 craigs 00066 * Added locking functions and LoadURL function 00067 * 00068 * Revision 1.14 2002/11/06 22:47:24 robertj 00069 * Fixed header comment (copyright etc) 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 & /*elementName*/ 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 // static methods to create XML tags 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; // stupid gcc 4 does not recognize PConfig as a class 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