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

Generated on Fri Mar 7 06:25:02 2008 for PTLib by  doxygen 1.5.1