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.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

Generated on Fri Sep 21 14:40:11 2007 for PWLib by  doxygen 1.5.3