pxml.h

Go to the documentation of this file.
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  * $Revision: 20385 $
00027  * $Author: rjongbloed $
00028  * $Date: 2008-06-04 10:40:38 +0000 (Wed, 04 Jun 2008) $
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 & /*elementName*/
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     // static methods to create XML tags
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;      // stupid gcc 4 does not recognize PConfig as a class
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

Generated on Mon Sep 15 01:21:35 2008 for PTLib by  doxygen 1.5.1