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: 24286 $
00027  * $Author: csoutheren $
00028  * $Date: 2010-04-27 07:31:32 -0500 (Tue, 27 Apr 2010) $
00029  */
00030 
00031 #ifndef PTLIB_PXML_H
00032 #define PTLIB_PXML_H
00033 
00034 #ifdef P_USE_PRAGMA
00035 #pragma interface
00036 #endif
00037 
00038 #include <ptlib.h>
00039 
00040 #include <ptbuildopts.h>
00041 
00042 #ifndef P_EXPAT
00043 
00044 namespace PXML {
00045 extern PString EscapeSpecialChars(const PString & str);
00046 };
00047 
00048 #else
00049 
00050 #include <ptclib/http.h>
00051 
00053 
00054 class PXMLElement;
00055 class PXMLData;
00056 
00057 
00058 class PXMLObject;
00059 class PXMLElement;
00060 class PXMLData;
00061 
00063 
00064 class PXMLBase : public PObject
00065 {
00066   public:
00067     enum Options {
00068       NoOptions           = 0x0000,
00069       Indent              = 0x0001,
00070       NewLineAfterElement = 0x0002,
00071       NoIgnoreWhiteSpace  = 0x0004,   
00072       CloseExtended       = 0x0008,   
00073       WithNS              = 0x0010,
00074       FragmentOnly        = 0x0020,   
00075       AllOptions          = 0xffff
00076     };
00077     __inline friend Options operator|(Options o1, Options o2) { return (Options)(((unsigned)o1) | ((unsigned)o2)); }
00078     __inline friend Options operator&(Options o1, Options o2) { return (Options)(((unsigned)o1) & ((unsigned)o2)); }
00079 
00080     enum StandAloneType {
00081       UninitialisedStandAlone = -2,
00082       UnknownStandAlone = -1,
00083       NotStandAlone,
00084       IsStandAlone
00085     };
00086 
00087     PXMLBase(int opts = NoOptions)
00088       : m_options(opts) { }
00089 
00090     void SetOptions(int opts)
00091       { m_options = opts; }
00092 
00093     int GetOptions() const { return m_options; }
00094 
00095     virtual PBoolean IsNoIndentElement(
00096       const PString & /*elementName*/
00097     ) const
00098     {
00099       return false;
00100     }
00101 
00102   protected:
00103     int m_options;
00104 };
00105 
00106 
00107 class PXML : public PXMLBase
00108 {
00109   PCLASSINFO(PXML, PObject);
00110   public:
00111 
00112     PXML(
00113       int options = NoOptions,
00114       const char * noIndentElements = NULL
00115     );
00116     PXML(
00117       const PString & data,
00118       int options = NoOptions,
00119       const char * noIndentElements = NULL
00120     );
00121 
00122     PXML(const PXML & xml);
00123 
00124     ~PXML();
00125 
00126     bool IsLoaded() const { return rootElement != NULL; }
00127     bool IsDirty() const;
00128 
00129     bool Load(const PString & data, Options options = NoOptions);
00130 
00131 #if P_HTTP
00132     bool StartAutoReloadURL(
00133       const PURL & url, 
00134       const PTimeInterval & timeout, 
00135       const PTimeInterval & refreshTime,
00136       Options options = NoOptions
00137     );
00138     bool StopAutoReloadURL();
00139     PString GetAutoReloadStatus() { PWaitAndSignal m(autoLoadMutex); PString str = autoLoadError; return str; }
00140     bool AutoLoadURL();
00141     virtual void OnAutoLoad(PBoolean ok);
00142 
00143     bool LoadURL(const PURL & url);
00144     bool LoadURL(const PURL & url, const PTimeInterval & timeout, Options options = NoOptions);
00145 #endif // P_HTTP
00146 
00147     bool LoadFile(const PFilePath & fn, Options options = NoOptions);
00148 
00149     virtual void OnLoaded() { }
00150 
00151     bool Save(Options options = NoOptions);
00152     bool Save(PString & data, Options options = NoOptions);
00153     bool SaveFile(const PFilePath & fn, Options options = NoOptions);
00154 
00155     void RemoveAll();
00156 
00157     PBoolean IsNoIndentElement(
00158       const PString & elementName
00159     ) const;
00160 
00161     PString AsString() const;
00162     void PrintOn(ostream & strm) const;
00163     void ReadFrom(istream & strm);
00164 
00165 
00166     PXMLElement * GetElement(const PCaselessString & name, const PCaselessString & attr, const PString & attrval) const;
00167     PXMLElement * GetElement(const PCaselessString & name, PINDEX idx = 0) const;
00168     PXMLElement * GetElement(PINDEX idx) const;
00169     PINDEX        GetNumElements() const; 
00170     PXMLElement * GetRootElement() const { return rootElement; }
00171     PXMLElement * SetRootElement(PXMLElement * p);
00172     PXMLElement * SetRootElement(const PString & documentType);
00173     bool          RemoveElement(PINDEX idx);
00174 
00175     PCaselessString GetDocumentType() const;
00176 
00177 
00178     enum ValidationOp {
00179       EndOfValidationList,
00180       DocType,
00181       ElementName,
00182       RequiredAttribute,
00183       RequiredNonEmptyAttribute,
00184       RequiredAttributeWithValue,
00185       RequiredElement,
00186       Subtree,
00187       RequiredAttributeWithValueMatching,
00188       RequiredElementWithBodyMatching,
00189       OptionalElement,
00190       OptionalAttribute,
00191       OptionalNonEmptyAttribute,
00192       OptionalAttributeWithValue,
00193       OptionalAttributeWithValueMatching,
00194       OptionalElementWithBodyMatching,
00195       SetDefaultNamespace,
00196       SetNamespace,
00197 
00198       RequiredAttributeWithValueMatchingEx = RequiredAttributeWithValueMatching + 0x8000,
00199       OptionalAttributeWithValueMatchingEx = OptionalAttributeWithValueMatching + 0x8000,
00200       RequiredElementWithBodyMatchingEx    = RequiredElementWithBodyMatching    + 0x8000,
00201       OptionalElementWithBodyMatchingEx    = OptionalElementWithBodyMatching    + 0x8000
00202     };
00203 
00204     struct ValidationContext {
00205       PString m_defaultNameSpace;
00206       PStringToString m_nameSpaces;
00207     };
00208 
00209     struct ValidationInfo {
00210       ValidationOp m_op;
00211       const char * m_name;
00212 
00213       union {
00214         const void     * m_placeHolder;
00215         const char     * m_attributeValues;
00216         ValidationInfo * m_subElement;
00217         const char     * m_namespace;
00218       };
00219 
00220       PINDEX m_minCount;
00221       PINDEX m_maxCount;
00222     };
00223 
00224     bool Validate(const ValidationInfo * validator);
00225     bool ValidateElements(ValidationContext & context, PXMLElement * baseElement, const ValidationInfo * elements);
00226     bool ValidateElement(ValidationContext & context, PXMLElement * element, const ValidationInfo * elements);
00227 
00228     PString  GetErrorString() const { return m_errorString; }
00229     unsigned GetErrorColumn() const { return m_errorColumn; }
00230     unsigned GetErrorLine() const   { return m_errorLine; }
00231 
00232     PString GetDocType() const         { return docType; }
00233     void SetDocType(const PString & v) { docType = v; }
00234 
00235     PMutex & GetMutex() { return rootMutex; }
00236 
00237 #if P_HTTP
00238     PDECLARE_NOTIFIER(PTimer,  PXML, AutoReloadTimeout);
00239     PDECLARE_NOTIFIER(PThread, PXML, AutoReloadThread);
00240 #endif // P_HTTP
00241 
00242     // static methods to create XML tags
00243     static PString CreateStartTag (const PString & text);
00244     static PString CreateEndTag (const PString & text);
00245     static PString CreateTagNoData (const PString & text);
00246     static PString CreateTag (const PString & text, const PString & data);
00247 
00248     static PString EscapeSpecialChars(const PString & string);
00249 
00250   protected:
00251     void Construct(int options, const char * noIndentElements);
00252     PXMLElement * rootElement;
00253     PMutex rootMutex;
00254 
00255     bool loadFromFile;
00256     PFilePath loadFilename;
00257     PString version, encoding;
00258     StandAloneType m_standAlone;
00259 
00260 #if P_HTTP
00261     PTimer autoLoadTimer;
00262     PURL autoloadURL;
00263     PTimeInterval autoLoadWaitTime;
00264     PMutex autoLoadMutex;
00265     PString autoLoadError;
00266 #endif // P_HTTP
00267 
00268     PStringStream m_errorString;
00269     unsigned      m_errorLine;
00270     unsigned      m_errorColumn;
00271 
00272     PSortedStringList noIndentElements;
00273 
00274     PString docType;
00275     PString m_defaultNameSpace;
00276 };
00277 
00279 
00280 PARRAY(PXMLObjectArray, PXMLObject);
00281 
00282 class PXMLObject : public PObject {
00283   PCLASSINFO(PXMLObject, PObject);
00284   public:
00285     PXMLObject(PXMLElement * par)
00286       : parent(par) { dirty = false; }
00287 
00288     PXMLElement * GetParent() const
00289       { return parent; }
00290 
00291     PXMLObject * GetNextObject() const;
00292 
00293     void SetParent(PXMLElement * newParent)
00294     { 
00295       PAssert(parent == NULL, "Cannot reparent PXMLElement");
00296       parent = newParent;
00297     }
00298 
00299     PString AsString() const;
00300 
00301     virtual void Output(ostream & strm, const PXMLBase & xml, int indent) const = 0;
00302 
00303     virtual PBoolean IsElement() const = 0;
00304 
00305     void SetDirty();
00306     bool IsDirty() const { return dirty; }
00307 
00308     virtual PXMLObject * Clone(PXMLElement * parent) const = 0;
00309 
00310   protected:
00311     PXMLElement * parent;
00312     bool dirty;
00313 };
00314 
00316 
00317 class PXMLData : public PXMLObject {
00318   PCLASSINFO(PXMLData, PXMLObject);
00319   public:
00320     PXMLData(PXMLElement * parent, const PString & data);
00321     PXMLData(PXMLElement * parent, const char * data, int len);
00322 
00323     PBoolean IsElement() const    { return false; }
00324 
00325     void SetString(const PString & str, bool dirty = true);
00326 
00327     PString GetString() const           { return value; }
00328 
00329     void Output(ostream & strm, const PXMLBase & xml, int indent) const;
00330 
00331     PXMLObject * Clone(PXMLElement * parent) const;
00332 
00333   protected:
00334     PString value;
00335 };
00336 
00338 
00339 class PXMLElement : public PXMLObject {
00340   PCLASSINFO(PXMLElement, PXMLObject);
00341   public:
00342     PXMLElement(PXMLElement * parent, const char * name = NULL);
00343     PXMLElement(PXMLElement * parent, const PString & name, const PString & data);
00344 
00345     PBoolean IsElement() const { return true; }
00346 
00347     void PrintOn(ostream & strm) const;
00348     void Output(ostream & strm, const PXMLBase & xml, int indent) const;
00349 
00350     PCaselessString GetName() const
00351       { return name; }
00352 
00357     PCaselessString GetPathName() const;
00358 
00359     void SetName(const PString & v)
00360     { name = v; }
00361 
00362     PINDEX GetSize() const
00363       { return subObjects.GetSize(); }
00364 
00365     PXMLObject  * AddSubObject(PXMLObject * elem, bool dirty = true);
00366 
00367     PXMLElement * AddChild    (PXMLElement * elem, bool dirty = true);
00368     PXMLData    * AddChild    (PXMLData    * elem, bool dirty = true);
00369 
00370     PXMLElement * AddElement(const char * name);
00371     PXMLElement * AddElement(const PString & name, const PString & data);
00372     PXMLElement * AddElement(const PString & name, const PString & attrName, const PString & attrVal);
00373 
00374     void SetAttribute(const PCaselessString & key,
00375                       const PString & value,
00376                       bool setDirty = true);
00377 
00378     PString GetAttribute(const PCaselessString & key) const;
00379     PString GetKeyAttribute(PINDEX idx) const;
00380     PString GetDataAttribute(PINDEX idx) const;
00381     bool HasAttribute(const PCaselessString & key) const;
00382     bool HasAttributes() const      { return attributes.GetSize() > 0; }
00383     PINDEX GetNumAttributes() const { return attributes.GetSize(); }
00384 
00385     PXMLElement * GetElement(const PCaselessString & name, const PCaselessString & attr, const PString & attrval) const;
00386     PXMLElement * GetElement(const PCaselessString & name, PINDEX idx = 0) const;
00387     PXMLObject  * GetElement(PINDEX idx = 0) const;
00388     bool          RemoveElement(PINDEX idx);
00389 
00390     PINDEX FindObject(const PXMLObject * ptr) const;
00391 
00392     bool HasSubObjects() const
00393       { return subObjects.GetSize() != 0; }
00394 
00395     PXMLObjectArray  GetSubObjects() const
00396       { return subObjects; }
00397 
00398     PString GetData() const;
00399     void SetData(const PString & data);
00400     void AddData(const PString & data);
00401 
00402     PXMLObject * Clone(PXMLElement * parent) const;
00403 
00404     void GetFilePosition(unsigned & col, unsigned & line) const { col = column; line = lineNumber; }
00405     void SetFilePosition(unsigned col,   unsigned line)         { column = col; lineNumber = line; }
00406 
00407     void AddNamespace(const PString & prefix, const PString & uri);
00408     void RemoveNamespace(const PString & prefix);
00409 
00410     bool GetDefaultNamespace(PCaselessString & str) const;
00411     bool GetNamespace(const PCaselessString & prefix, PCaselessString & str) const;
00412     PCaselessString PrependNamespace(const PCaselessString & name) const;
00413     bool GetURIForNamespace(const PCaselessString & prefix, PCaselessString & uri);
00414 
00415   protected:
00416     PCaselessString name;
00417     PStringToString attributes;
00418     PXMLObjectArray subObjects;
00419     bool dirty;
00420     unsigned column;
00421     unsigned lineNumber;
00422     PStringToString m_nameSpaces;
00423     PCaselessString m_defaultNamespace;
00424 };
00425 
00427 
00428 class PConfig;      // stupid gcc 4 does not recognize PConfig as a class
00429 
00430 class PXMLSettings : public PXML
00431 {
00432   PCLASSINFO(PXMLSettings, PXML);
00433   public:
00434     PXMLSettings(Options options = NewLineAfterElement);
00435     PXMLSettings(const PString & data, Options options = NewLineAfterElement);
00436     PXMLSettings(const PConfig & data, Options options = NewLineAfterElement);
00437 
00438     bool Load(const PString & data);
00439     bool LoadFile(const PFilePath & fn);
00440 
00441     bool Save();
00442     bool Save(PString & data);
00443     bool SaveFile(const PFilePath & fn);
00444 
00445     void SetAttribute(const PCaselessString & section, const PString & key, const PString & value);
00446 
00447     PString GetAttribute(const PCaselessString & section, const PString & key) const;
00448     bool    HasAttribute(const PCaselessString & section, const PString & key) const;
00449 
00450     void ToConfig(PConfig & cfg) const;
00451 };
00452 
00453 
00455 
00456 class PXMLParser : public PXMLBase
00457 {
00458   PCLASSINFO(PXMLParser, PXMLBase);
00459   public:
00460     PXMLParser(int options = NoOptions);
00461     ~PXMLParser();
00462     bool Parse(const char * data, int dataLen, bool final);
00463     void GetErrorInfo(PString & errorString, unsigned & errorCol, unsigned & errorLine);
00464 
00465     virtual void StartElement(const char * name, const char **attrs);
00466     virtual void EndElement(const char * name);
00467     virtual void AddCharacterData(const char * data, int len);
00468     virtual void XmlDecl(const char * version, const char * encoding, int standAlone);
00469     virtual void StartDocTypeDecl(const char * docTypeName,
00470                                   const char * sysid,
00471                                   const char * pubid,
00472                                   int hasInternalSubSet);
00473     virtual void EndDocTypeDecl();
00474     virtual void StartNamespaceDeclHandler(const char * prefix, const char * uri);
00475     virtual void EndNamespaceDeclHandler(const char * prefix);
00476 
00477     PString GetVersion() const  { return version; }
00478     PString GetEncoding() const { return encoding; }
00479 
00480     StandAloneType GetStandAlone() const { return m_standAlone; }
00481 
00482     PXMLElement * GetXMLTree() const;
00483     PXMLElement * SetXMLTree(PXMLElement * newRoot);
00484 
00485   protected:
00486     void * expat;
00487     PXMLElement * rootElement;
00488     bool rootOpen;
00489     PXMLElement * currentElement;
00490     PXMLData * lastElement;
00491     PString version, encoding;
00492     StandAloneType m_standAlone;
00493     PStringToString m_tempNamespaceList;
00494 };
00495 
00497 
00498 class PXMLStreamParser : public PXMLParser
00499 {
00500   PCLASSINFO(PXMLStreamParser, PXMLParser);
00501   public:
00502     PXMLStreamParser();
00503 
00504     virtual void EndElement(const char * name);
00505     virtual PXML * Read(PChannel * channel);
00506 
00507   protected:
00508     PQueue<PXML> messages;
00509 };
00510 
00511 
00512 #endif // P_EXPAT
00513 
00514 #endif // PTLIB_PXML_H
00515 
00516 
00517 // End Of File ///////////////////////////////////////////////////////////////

Generated on Fri Oct 14 01:44:10 2011 for PTLib by  doxygen 1.4.7