Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Class Members | File Members

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  * $Log: pxml.h,v $
00027  * Revision 1.24  2004/10/12 23:28:07  csoutheren
00028  * Fixed problem with bogus DOCTYPE being output
00029  *
00030  * Revision 1.23  2004/04/21 00:35:02  csoutheren
00031  * Added a stream parser for protocols like XMPP where each child of the root is to be considered a separate document/message.
00032  * Thanks to Federico Pinna and Reitek S.p.A.
00033  *
00034  * Revision 1.22  2003/04/27 23:54:13  craigs
00035  * Removed deprecated options
00036  *
00037  * Revision 1.21  2003/03/31 07:41:50  craigs
00038  * Fixed problem with accidental introduced dependency on expat.h
00039  *
00040  * Revision 1.20  2003/03/31 06:21:19  craigs
00041  * Split the expat wrapper from the XML file handling to allow reuse of the parser
00042  *
00043  * Revision 1.19  2003/01/13 02:14:02  robertj
00044  * Improved error logging for auto-loaded XML
00045  *
00046  * Revision 1.18  2002/12/16 06:38:24  robertj
00047  * Added ability to specify certain elemets (by name) that are exempt from
00048  *   the indent formatting. Useful for XML/RPC where leading white space is
00049  *   not ignored by all servers.
00050  *
00051  * Revision 1.17  2002/11/26 05:53:57  craigs
00052  * Added ability to auto-reload from URL
00053  *
00054  * Revision 1.16  2002/11/21 08:09:04  craigs
00055  * Changed to not overwrite XML data if load fails
00056  *
00057  * Revision 1.15  2002/11/19 07:37:38  craigs
00058  * Added locking functions and LoadURL function
00059  *
00060  * Revision 1.14  2002/11/06 22:47:24  robertj
00061  * Fixed header comment (copyright etc)
00062  *
00063  */
00064 
00065 #ifndef _PXML_H
00066 #define _PXML_H
00067 
00068 #ifdef P_USE_PRAGMA
00069 #pragma interface
00070 #endif
00071 
00072 #include <ptlib.h>
00073 #include <ptclib/http.h>
00074 
00076 
00077 class PXMLElement;
00078 class PXMLData;
00079 
00080 class PXMLParser : public PObject
00081 {
00082   PCLASSINFO(PXMLParser, PObject);
00083   public:
00084     enum Options {
00085       Indent              = 1,
00086       NewLineAfterElement = 2,
00087       NoIgnoreWhiteSpace  = 4,   // ignored
00088       CloseExtended       = 8,   // ignored
00089       WithNS              = 16,
00090     };
00091 
00092     PXMLParser(int options = -1);
00093     ~PXMLParser();
00094     BOOL Parse(const char * data, int dataLen, BOOL final);
00095     void GetErrorInfo(PString & errorString, PINDEX & errorCol, PINDEX & errorLine);
00096 
00097     virtual void StartElement(const char * name, const char **attrs);
00098     virtual void EndElement(const char * name);
00099     virtual void AddCharacterData(const char * data, int len);
00100     virtual void XmlDecl(const char * version, const char * encoding, int standAlone);
00101     virtual void StartDocTypeDecl(const char * docTypeName,
00102                                               const char * sysid,
00103                                                           const char * pubid,
00104                                                           int hasInternalSubSet);
00105     virtual void EndDocTypeDecl();
00106     virtual void StartNamespaceDeclHandler(const char * prefix, const char * uri);
00107     virtual void EndNamespaceDeclHandler(const char * prefix);
00108 
00109     PString GetVersion() const  { return version; }
00110     PString GetEncoding() const { return encoding; }
00111     BOOL GetStandAlone() const  { return standAlone; }
00112 
00113     PXMLElement * GetXMLTree() const;
00114     PXMLElement * SetXMLTree(PXMLElement * newRoot);
00115 
00116   protected:
00117     int options;
00118     void * expat;
00119     PXMLElement * rootElement;
00120     PXMLElement * currentElement;
00121     PXMLData * lastElement;
00122     PString version, encoding;
00123     int standAlone;
00124 };
00125 
00126 class PXMLObject;
00127 class PXMLElement;
00128 class PXMLData;
00129 
00131 
00132 class PXMLBase : public PObject
00133 {
00134   public:
00135     PXMLBase(int _options = -1)
00136       : options(_options) { if (options < 0) options = 0; }
00137 
00138     void SetOptions(int _options)
00139       { options = _options; }
00140 
00141     int GetOptions() const { return options; }
00142 
00143     virtual BOOL IsNoIndentElement(
00144       const PString & /*elementName*/
00145     ) const
00146     {
00147       return FALSE;
00148     }
00149 
00150   protected:
00151     int options;
00152 };
00153 
00154 
00155 class PXML : public PXMLBase
00156 {
00157   PCLASSINFO(PXML, PObject);
00158   public:
00159 
00160     PXML(
00161       int options = -1,
00162       const char * noIndentElements = NULL
00163     );
00164     PXML(
00165       const PString & data,
00166       int options = -1,
00167       const char * noIndentElements = NULL
00168     );
00169 
00170     PXML(const PXML & xml);
00171 
00172     ~PXML();
00173 
00174     BOOL IsDirty() const;
00175 
00176     BOOL Load(const PString & data, int options = -1);
00177 
00178     BOOL StartAutoReloadURL(const PURL & url, 
00179                             const PTimeInterval & timeout, 
00180                             const PTimeInterval & refreshTime,
00181                             int _options = -1);
00182     BOOL StopAutoReloadURL();
00183     PString GetAutoReloadStatus() { PWaitAndSignal m(autoLoadMutex); PString str = autoLoadError; return str; }
00184     BOOL AutoLoadURL();
00185     virtual void OnAutoLoad(BOOL ok);
00186 
00187     BOOL LoadURL(const PURL & url);
00188     BOOL LoadURL(const PURL & url, const PTimeInterval & timeout, int _options = -1);
00189     BOOL LoadFile(const PFilePath & fn, int options = -1);
00190 
00191     virtual void OnLoaded() { }
00192 
00193     BOOL Save(int options = -1);
00194     BOOL Save(PString & data, int options = -1);
00195     BOOL SaveFile(const PFilePath & fn, int options = -1);
00196 
00197     void RemoveAll();
00198 
00199     BOOL IsNoIndentElement(
00200       const PString & elementName
00201     ) const;
00202 
00203     void PrintOn(ostream & strm) const;
00204 
00205     PXMLElement * GetElement(const PCaselessString & name, PINDEX idx = 0) const;
00206     PXMLElement * GetElement(PINDEX idx) const;
00207     PINDEX        GetNumElements() const; 
00208     PXMLElement * GetRootElement() const { return rootElement; }
00209     PXMLElement * SetRootElement(PXMLElement * p);
00210     PXMLElement * SetRootElement(const PString & documentType);
00211     BOOL          RemoveElement(PINDEX idx);
00212 
00213     PCaselessString GetDocumentType() const;
00214 
00215     PString GetErrorString() const { return errorString; }
00216     PINDEX  GetErrorColumn() const { return errorCol; }
00217     PINDEX  GetErrorLine() const   { return errorLine; }
00218 
00219     PString GetDocType() const         { return docType; }
00220     void SetDocType(const PString & v) { docType = v; }
00221 
00222     PMutex & GetMutex() { return rootMutex; }
00223 
00224     PDECLARE_NOTIFIER(PTimer,  PXML, AutoReloadTimeout);
00225     PDECLARE_NOTIFIER(PThread, PXML, AutoReloadThread);
00226 
00227     // static methods to create XML tags
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   protected:
00234     void Construct(int options, const char * noIndentElements);
00235     PXMLElement * rootElement;
00236     PMutex rootMutex;
00237 
00238     BOOL loadFromFile;
00239     PFilePath loadFilename;
00240     PString version, encoding;
00241     int standAlone;
00242 
00243     PTimer autoLoadTimer;
00244     PURL autoloadURL;
00245     PTimeInterval autoLoadWaitTime;
00246     PMutex autoLoadMutex;
00247     PString autoLoadError;
00248 
00249     PString errorString;
00250     PINDEX errorCol;
00251     PINDEX errorLine;
00252 
00253     PSortedStringList noIndentElements;
00254 
00255     PString docType;
00256 };
00257 
00259 
00260 PARRAY(PXMLObjectArray, PXMLObject);
00261 
00262 class PXMLObject : public PObject {
00263   PCLASSINFO(PXMLObject, PObject);
00264   public:
00265     PXMLObject(PXMLElement * _parent)
00266       : parent(_parent) { dirty = FALSE; }
00267 
00268     PXMLElement * GetParent()
00269       { return parent; }
00270 
00271     PXMLObject * GetNextObject();
00272 
00273     void SetParent(PXMLElement * newParent)
00274     { 
00275       PAssert(parent == NULL, "Cannot reparent PXMLElement");
00276       parent = newParent;
00277     }
00278 
00279     virtual void Output(ostream & strm, const PXMLBase & xml, int indent) const = 0;
00280 
00281     virtual BOOL IsElement() const = 0;
00282 
00283     void SetDirty();
00284     BOOL IsDirty() const { return dirty; }
00285 
00286     virtual PXMLObject * Clone(PXMLElement * parent) const = 0;
00287 
00288   protected:
00289     PXMLElement * parent;
00290     BOOL dirty;
00291 };
00292 
00294 
00295 class PXMLData : public PXMLObject {
00296   PCLASSINFO(PXMLData, PXMLObject);
00297   public:
00298     PXMLData(PXMLElement * _parent, const PString & data);
00299     PXMLData(PXMLElement * _parent, const char * data, int len);
00300 
00301     BOOL IsElement() const    { return FALSE; }
00302 
00303     void SetString(const PString & str, BOOL dirty = TRUE);
00304 
00305     PString GetString() const           { return value; }
00306 
00307     void Output(ostream & strm, const PXMLBase & xml, int indent) const;
00308 
00309     PXMLObject * Clone(PXMLElement * parent) const;
00310 
00311   protected:
00312     PString value;
00313 };
00314 
00316 
00317 class PXMLElement : public PXMLObject {
00318   PCLASSINFO(PXMLElement, PXMLObject);
00319   public:
00320     PXMLElement(PXMLElement * _parent, const char * name = NULL);
00321     PXMLElement(PXMLElement * _parent, const PString & name, const PString & data);
00322 
00323     BOOL IsElement() const { return TRUE; }
00324 
00325     void PrintOn(ostream & strm) const;
00326     void Output(ostream & strm, const PXMLBase & xml, int indent) const;
00327 
00328     PCaselessString GetName() const
00329       { return name; }
00330 
00331     void SetName(const PString & v)
00332       { name = v; }
00333 
00334     PINDEX GetSize() const
00335       { return subObjects.GetSize(); }
00336 
00337     PXMLObject  * AddSubObject(PXMLObject * elem, BOOL dirty = TRUE);
00338 
00339     PXMLElement * AddChild    (PXMLElement * elem, BOOL dirty = TRUE);
00340     PXMLData    * AddChild    (PXMLData    * elem, BOOL dirty = TRUE);
00341 
00342     void SetAttribute(const PCaselessString & key,
00343                                   const PString & value,
00344                       BOOL setDirty = TRUE);
00345 
00346     PString GetAttribute(const PCaselessString & key) const;
00347     PString GetKeyAttribute(PINDEX idx) const;
00348     PString GetDataAttribute(PINDEX idx) const;
00349     BOOL HasAttribute(const PCaselessString & key);
00350     BOOL HasAttributes() const      { return attributes.GetSize() > 0; }
00351     PINDEX GetNumAttributes() const { return attributes.GetSize(); }
00352 
00353     PXMLElement * GetElement(const PCaselessString & name, PINDEX idx = 0) const;
00354     PXMLObject  * GetElement(PINDEX idx = 0) const;
00355     BOOL          RemoveElement(PINDEX idx);
00356 
00357     PINDEX FindObject(PXMLObject * ptr) const;
00358 
00359     BOOL HasSubObjects() const
00360       { return subObjects.GetSize() != 0; }
00361 
00362     PXMLObjectArray  GetSubObjects() const
00363       { return subObjects; }
00364 
00365     PString GetData() const;
00366 
00367     PXMLObject * Clone(PXMLElement * parent) const;
00368 
00369   protected:
00370     PCaselessString name;
00371     PStringToString attributes;
00372     PXMLObjectArray subObjects;
00373     BOOL dirty;
00374 };
00375 
00377 
00378 class PXMLSettings : public PXML
00379 {
00380   PCLASSINFO(PXMLSettings, PXML);
00381   public:
00382     PXMLSettings(int options = PXMLParser::NewLineAfterElement);
00383     PXMLSettings(const PString & data, int options = PXMLParser::NewLineAfterElement);
00384     PXMLSettings(const PConfig & data, int options = PXMLParser::NewLineAfterElement);
00385 
00386     BOOL Load(const PString & data);
00387     BOOL LoadFile(const PFilePath & fn);
00388 
00389     BOOL Save();
00390     BOOL Save(PString & data);
00391     BOOL SaveFile(const PFilePath & fn);
00392 
00393     void SetAttribute(const PCaselessString & section, const PString & key, const PString & value);
00394 
00395     PString GetAttribute(const PCaselessString & section, const PString & key) const;
00396     BOOL    HasAttribute(const PCaselessString & section, const PString & key) const;
00397 
00398     void ToConfig(PConfig & cfg) const;
00399 };
00400 
00402 
00403 class PXMLStreamParser : public PXMLParser
00404 {
00405   PCLASSINFO(PXMLStreamParser, PXMLParser);
00406   public:
00407     PXMLStreamParser();
00408 
00409     virtual void EndElement(const char * name);
00410     virtual PXML * Read(PChannel * channel);
00411 
00412   protected:
00413     BOOL rootOpen;
00414     PQueue<PXML> messages;
00415 };
00416 
00417 #endif

Generated on Wed Sep 28 10:27:33 2005 for PWLib by  doxygen 1.4.4