PTLib  Version 2.10.4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
pxml.h
Go to the documentation of this file.
1 /*
2  * pxml.h
3  *
4  * XML parser support
5  *
6  * Portable Windows Library
7  *
8  * Copyright (c) 2002 Equivalence Pty. Ltd.
9  *
10  * The contents of this file are subject to the Mozilla Public License
11  * Version 1.0 (the "License"); you may not use this file except in
12  * compliance with the License. You may obtain a copy of the License at
13  * http://www.mozilla.org/MPL/
14  *
15  * Software distributed under the License is distributed on an "AS IS"
16  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17  * the License for the specific language governing rights and limitations
18  * under the License.
19  *
20  * The Original Code is Portable Windows Library.
21  *
22  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
23  *
24  * Contributor(s): ______________________________________.
25  *
26  * $Revision: 24995 $
27  * $Author: csoutheren $
28  * $Date: 2011-01-04 19:12:33 -0600 (Tue, 04 Jan 2011) $
29  */
30 
31 #ifndef PTLIB_PXML_H
32 #define PTLIB_PXML_H
33 
34 #ifdef P_USE_PRAGMA
35 #pragma interface
36 #endif
37 
38 #include <ptlib.h>
39 
40 #include <ptbuildopts.h>
41 
42 #ifndef P_EXPAT
43 
44 namespace PXML {
45 extern PString EscapeSpecialChars(const PString & str);
46 };
47 
48 #else
49 
50 #include <ptclib/http.h>
51 
53 
54 class PXMLElement;
55 class PXMLData;
56 
57 
58 class PXMLObject;
59 class PXMLElement;
60 class PXMLData;
61 
63 
64 class PXMLBase : public PObject
65 {
66  public:
67  enum Options {
68  NoOptions = 0x0000,
69  Indent = 0x0001,
71  NoIgnoreWhiteSpace = 0x0004,
72  CloseExtended = 0x0008,
73  WithNS = 0x0010,
74  FragmentOnly = 0x0020,
75  AllOptions = 0xffff
76  };
77  __inline friend Options operator|(Options o1, Options o2) { return (Options)(((unsigned)o1) | ((unsigned)o2)); }
78  __inline friend Options operator&(Options o1, Options o2) { return (Options)(((unsigned)o1) & ((unsigned)o2)); }
79 
85  };
86 
87  PXMLBase(int opts = NoOptions)
88  : m_options(opts) { }
89 
90  void SetOptions(int opts)
91  { m_options = opts; }
92 
93  int GetOptions() const { return m_options; }
94 
96  const PString & /*elementName*/
97  ) const
98  {
99  return false;
100  }
101 
102  protected:
104 };
105 
106 
107 class PXML : public PXMLBase
108 {
109  PCLASSINFO(PXML, PObject);
110  public:
111 
112  PXML(
113  int options = NoOptions,
114  const char * noIndentElements = NULL
115  );
116  PXML(
117  const PString & data,
118  int options = NoOptions,
119  const char * noIndentElements = NULL
120  );
121 
122  PXML(const PXML & xml);
123 
124  ~PXML();
125 
126  bool IsLoaded() const { return rootElement != NULL; }
127  bool IsDirty() const;
128 
129  bool Load(const PString & data, Options options = NoOptions);
130 
131 #if P_HTTP
132  bool StartAutoReloadURL(
133  const PURL & url,
134  const PTimeInterval & timeout,
135  const PTimeInterval & refreshTime,
136  Options options = NoOptions
137  );
138  bool StopAutoReloadURL();
140  bool AutoLoadURL();
141  virtual void OnAutoLoad(PBoolean ok);
142 
143  bool LoadURL(const PURL & url);
144  bool LoadURL(const PURL & url, const PTimeInterval & timeout, Options options = NoOptions);
145 #endif // P_HTTP
146 
147  bool LoadFile(const PFilePath & fn, Options options = NoOptions);
148 
149  virtual void OnLoaded() { }
150 
151  bool Save(Options options = NoOptions);
152  bool Save(PString & data, Options options = NoOptions);
153  bool SaveFile(const PFilePath & fn, Options options = NoOptions);
154 
155  void RemoveAll();
156 
158  const PString & elementName
159  ) const;
160 
161  PString AsString() const;
162  void PrintOn(ostream & strm) const;
163  void ReadFrom(istream & strm);
164 
165 
166  PXMLElement * GetElement(const PCaselessString & name, const PCaselessString & attr, const PString & attrval) const;
167  PXMLElement * GetElement(const PCaselessString & name, PINDEX idx = 0) const;
168  PXMLElement * GetElement(PINDEX idx) const;
169  PINDEX GetNumElements() const;
170  PXMLElement * GetRootElement() const { return rootElement; }
172  PXMLElement * SetRootElement(const PString & documentType);
173  bool RemoveElement(PINDEX idx);
174 
176 
177 
197 
202  };
203 
207  };
208 
209  struct ValidationInfo {
211  const char * m_name;
212 
213  union {
214  const void * m_placeHolder;
215  const char * m_attributeValues;
217  const char * m_namespace;
218  };
219 
220  PINDEX m_minCount;
221  PINDEX m_maxCount;
222  };
223 
224  bool Validate(const ValidationInfo * validator);
225  bool ValidateElements(ValidationContext & context, PXMLElement * baseElement, const ValidationInfo * elements);
226  bool ValidateElement(ValidationContext & context, PXMLElement * element, const ValidationInfo * elements);
227  bool LoadAndValidate(const PString & body, const PXML::ValidationInfo * validator, PString & error, int options = NoOptions);
228 
230  unsigned GetErrorColumn() const { return m_errorColumn; }
231  unsigned GetErrorLine() const { return m_errorLine; }
232 
233  PString GetDocType() const { return docType; }
234  void SetDocType(const PString & v) { docType = v; }
235 
236  PMutex & GetMutex() { return rootMutex; }
237 
238 #if P_HTTP
239  PDECLARE_NOTIFIER(PTimer, PXML, AutoReloadTimeout);
240  PDECLARE_NOTIFIER(PThread, PXML, AutoReloadThread);
241 #endif // P_HTTP
242 
243  // static methods to create XML tags
244  static PString CreateStartTag (const PString & text);
245  static PString CreateEndTag (const PString & text);
246  static PString CreateTagNoData (const PString & text);
247  static PString CreateTag (const PString & text, const PString & data);
248 
249  static PString EscapeSpecialChars(const PString & string);
250 
251  protected:
252  void Construct(int options, const char * noIndentElements);
255 
260 
261 #if P_HTTP
267 #endif // P_HTTP
268 
270  unsigned m_errorLine;
271  unsigned m_errorColumn;
272 
274 
277 };
278 
280 
281 PARRAY(PXMLObjectArray, PXMLObject);
282 
283 class PXMLObject : public PObject {
284  PCLASSINFO(PXMLObject, PObject);
285  public:
287  : parent(par) { dirty = false; }
288 
290  { return parent; }
291 
292  PXMLObject * GetNextObject() const;
293 
294  void SetParent(PXMLElement * newParent)
295  {
296  PAssert(parent == NULL, "Cannot reparent PXMLElement");
297  parent = newParent;
298  }
299 
300  PString AsString() const;
301 
302  virtual void Output(ostream & strm, const PXMLBase & xml, int indent) const = 0;
303 
304  virtual PBoolean IsElement() const = 0;
305 
306  void SetDirty();
307  bool IsDirty() const { return dirty; }
308 
309  virtual PXMLObject * Clone(PXMLElement * parent) const = 0;
310 
311  protected:
313  bool dirty;
314 };
315 
317 
318 class PXMLData : public PXMLObject {
319  PCLASSINFO(PXMLData, PXMLObject);
320  public:
321  PXMLData(PXMLElement * parent, const PString & data);
322  PXMLData(PXMLElement * parent, const char * data, int len);
323 
324  PBoolean IsElement() const { return false; }
325 
326  void SetString(const PString & str, bool dirty = true);
327 
328  PString GetString() const { return value; }
329 
330  void Output(ostream & strm, const PXMLBase & xml, int indent) const;
331 
332  PXMLObject * Clone(PXMLElement * parent) const;
333 
334  protected:
336 };
337 
339 
340 class PXMLElement : public PXMLObject {
341  PCLASSINFO(PXMLElement, PXMLObject);
342  public:
343  PXMLElement(PXMLElement * parent, const char * name = NULL);
344  PXMLElement(PXMLElement * parent, const PString & name, const PString & data);
345 
346  PBoolean IsElement() const { return true; }
347 
348  void PrintOn(ostream & strm) const;
349  void Output(ostream & strm, const PXMLBase & xml, int indent) const;
350 
352  { return name; }
353 
359 
360  void SetName(const PString & v)
361  { name = v; }
362 
363  PINDEX GetSize() const
364  { return subObjects.GetSize(); }
365 
366  PXMLObject * AddSubObject(PXMLObject * elem, bool dirty = true);
367 
368  PXMLElement * AddChild (PXMLElement * elem, bool dirty = true);
369  PXMLData * AddChild (PXMLData * elem, bool dirty = true);
370 
371  PXMLElement * AddElement(const char * name);
372  PXMLElement * AddElement(const PString & name, const PString & data);
373  PXMLElement * AddElement(const PString & name, const PString & attrName, const PString & attrVal);
374 
375  void SetAttribute(const PCaselessString & key,
376  const PString & value,
377  bool setDirty = true);
378 
379  PString GetAttribute(const PCaselessString & key) const;
380  PString GetKeyAttribute(PINDEX idx) const;
381  PString GetDataAttribute(PINDEX idx) const;
382  bool HasAttribute(const PCaselessString & key) const;
383  bool HasAttributes() const { return attributes.GetSize() > 0; }
384  PINDEX GetNumAttributes() const { return attributes.GetSize(); }
385 
386  PXMLElement * GetElement(const PCaselessString & name, const PCaselessString & attr, const PString & attrval) const;
387  PXMLElement * GetElement(const PCaselessString & name, PINDEX idx = 0) const;
388  PXMLObject * GetElement(PINDEX idx = 0) const;
389  bool RemoveElement(PINDEX idx);
390 
391  PINDEX FindObject(const PXMLObject * ptr) const;
392 
393  bool HasSubObjects() const
394  { return subObjects.GetSize() != 0; }
395 
396  PXMLObjectArray GetSubObjects() const
397  { return subObjects; }
398 
399  PString GetData() const;
400  void SetData(const PString & data);
401  void AddData(const PString & data);
402 
403  PXMLObject * Clone(PXMLElement * parent) const;
404 
405  void GetFilePosition(unsigned & col, unsigned & line) const { col = column; line = lineNumber; }
406  void SetFilePosition(unsigned col, unsigned line) { column = col; lineNumber = line; }
407 
408  void AddNamespace(const PString & prefix, const PString & uri);
409  void RemoveNamespace(const PString & prefix);
410 
411  bool GetDefaultNamespace(PCaselessString & str) const;
412  bool GetNamespace(const PCaselessString & prefix, PCaselessString & str) const;
414  bool GetURIForNamespace(const PCaselessString & prefix, PCaselessString & uri);
415 
416  protected:
419  PXMLObjectArray subObjects;
420  bool dirty;
421  unsigned column;
422  unsigned lineNumber;
425 };
426 
428 
429 class PConfig; // stupid gcc 4 does not recognize PConfig as a class
430 
431 class PXMLSettings : public PXML
432 {
433  PCLASSINFO(PXMLSettings, PXML);
434  public:
436  PXMLSettings(const PString & data, Options options = NewLineAfterElement);
437  PXMLSettings(const PConfig & data, Options options = NewLineAfterElement);
438 
439  bool Load(const PString & data);
440  bool LoadFile(const PFilePath & fn);
441 
442  bool Save();
443  bool Save(PString & data);
444  bool SaveFile(const PFilePath & fn);
445 
446  void SetAttribute(const PCaselessString & section, const PString & key, const PString & value);
447 
448  PString GetAttribute(const PCaselessString & section, const PString & key) const;
449  bool HasAttribute(const PCaselessString & section, const PString & key) const;
450 
451  void ToConfig(PConfig & cfg) const;
452 };
453 
454 
456 
457 class PXMLParser : public PXMLBase
458 {
459  PCLASSINFO(PXMLParser, PXMLBase);
460  public:
461  PXMLParser(int options = NoOptions);
462  ~PXMLParser();
463  bool Parse(const char * data, int dataLen, bool final);
464  void GetErrorInfo(PString & errorString, unsigned & errorCol, unsigned & errorLine);
465 
466  virtual void StartElement(const char * name, const char **attrs);
467  virtual void EndElement(const char * name);
468  virtual void AddCharacterData(const char * data, int len);
469  virtual void XmlDecl(const char * version, const char * encoding, int standAlone);
470  virtual void StartDocTypeDecl(const char * docTypeName,
471  const char * sysid,
472  const char * pubid,
473  int hasInternalSubSet);
474  virtual void EndDocTypeDecl();
475  virtual void StartNamespaceDeclHandler(const char * prefix, const char * uri);
476  virtual void EndNamespaceDeclHandler(const char * prefix);
477 
478  PString GetVersion() const { return version; }
479  PString GetEncoding() const { return encoding; }
480 
482 
483  PXMLElement * GetXMLTree() const;
484  PXMLElement * SetXMLTree(PXMLElement * newRoot);
485 
486  protected:
487  void * expat;
489  bool rootOpen;
495 };
496 
498 
500 {
501  PCLASSINFO(PXMLStreamParser, PXMLParser);
502  public:
504 
505  virtual void EndElement(const char * name);
506  virtual PXML * Read(PChannel * channel);
507 
508  protected:
510 };
511 
512 
513 #endif // P_EXPAT
514 
515 #endif // PTLIB_PXML_H
516 
517 
518 // End Of File ///////////////////////////////////////////////////////////////