PTLib  Version 2.12.9
 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: 28997 $
27  * $Author: rjongbloed $
28  * $Date: 2013-01-26 13:37:28 +1100 (Sat, 26 Jan 2013) $
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 <ptlib/bitwise_enum.h>
51 #include <ptclib/http.h>
52 
53 
55 
56 class PXMLElement;
57 class PXMLData;
58 
59 
60 class PXMLObject;
61 class PXMLElement;
62 class PXMLData;
63 
65 
66 class PXMLBase : public PObject
67 {
68  public:
69  enum {
71  };
72 
73  P_DECLARE_BITWISE_ENUM_EX(Options, 6,
74  (NoOptions, Indent, NewLineAfterElement, NoIgnoreWhiteSpace, CloseExtended, WithNS, FragmentOnly),
75  AllOptions = (1<<(6+1))-1);
76 
82  };
83 
84  PXMLBase(Options opts = NoOptions);
85 
86  void SetOptions(Options opts) { m_options = opts; }
87  Options GetOptions() const { return m_options; }
88 
90  const PString & /*elementName*/
91  ) const
92  {
93  return false;
94  }
95 
96  void SetMaxEntityLength(unsigned len) { m_maxEntityLength = len; }
97  unsigned GetMaxEntityLength() const { return m_maxEntityLength; }
98 
99  protected:
100  Options m_options;
102 };
103 
104 
105 class PXML : public PXMLBase
106 {
107  PCLASSINFO(PXML, PObject);
108  public:
109  PXML(
110  Options options = NoOptions,
111  const char * noIndentElements = NULL
112  );
113 
114  PXML(const PXML & xml);
115 
116  ~PXML();
117 
118  bool IsLoaded() const { return rootElement != NULL; }
119  bool IsDirty() const;
120 
121  bool Load(const PString & data, Options options = NoOptions);
122  bool LoadFile(const PFilePath & fn, Options options = NoOptions);
123 
124  virtual void OnLoaded() { }
125 
126  bool Save(Options options = NoOptions);
127  PString AsString(Options options = NoOptions);
128  bool SaveFile(const PFilePath & fn, Options options = NoOptions);
129 
130  void RemoveAll();
131 
133  const PString & elementName
134  ) const;
135 
136  PString AsString() const;
137  void PrintOn(ostream & strm) const;
138  void ReadFrom(istream & strm);
139 
140 
141  PXMLElement * GetElement(const PCaselessString & name, const PCaselessString & attr, const PString & attrval) const;
142  PXMLElement * GetElement(const PCaselessString & name, PINDEX idx = 0) const;
143  PXMLElement * GetElement(PINDEX idx) const;
144  PINDEX GetNumElements() const;
145  PXMLElement * GetRootElement() const { return rootElement; }
147  PXMLElement * SetRootElement(const PString & documentType);
148  bool RemoveElement(PINDEX idx);
149 
151 
152 
172 
177  };
178 
182  };
183 
184  struct ValidationInfo {
186  const char * m_name;
187 
188  union {
189  const void * m_placeHolder;
190  const char * m_attributeValues;
192  const char * m_namespace;
193  };
194 
195  PINDEX m_minCount;
196  PINDEX m_maxCount;
197  };
198 
199  bool Validate(const ValidationInfo * validator);
200  bool ValidateElements(ValidationContext & context, PXMLElement * baseElement, const ValidationInfo * elements);
201  bool ValidateElement(ValidationContext & context, PXMLElement * element, const ValidationInfo * elements);
202  bool LoadAndValidate(const PString & body, const PXML::ValidationInfo * validator, PString & error, Options options = NoOptions);
203 
205  unsigned GetErrorColumn() const { return m_errorColumn; }
206  unsigned GetErrorLine() const { return m_errorLine; }
207 
208  PString GetDocType() const { return docType; }
209  void SetDocType(const PString & v) { docType = v; }
210 
211  PMutex & GetMutex() { return rootMutex; }
212 
213  // static methods to create XML tags
214  static PString CreateStartTag (const PString & text);
215  static PString CreateEndTag (const PString & text);
216  static PString CreateTagNoData (const PString & text);
217  static PString CreateTag (const PString & text, const PString & data);
218 
219  static PString EscapeSpecialChars(const PString & string);
220 
221  protected:
224 
229 
231  unsigned m_errorLine;
232  unsigned m_errorColumn;
233 
235 
238 };
239 
240 
241 #if P_HTTP
242 class PXML_HTTP : public PXML
243 {
244  PCLASSINFO(PXML_HTTP, PXML);
245  public:
246  PXML_HTTP(
247  Options options = NoOptions,
248  const char * noIndentElements = NULL
249  );
250 
251  bool StartAutoReloadURL(
252  const PURL & url,
253  const PTimeInterval & timeout,
254  const PTimeInterval & refreshTime,
255  Options options = NoOptions
256  );
257  bool StopAutoReloadURL();
259  bool AutoLoadURL();
260  virtual void OnAutoLoad(PBoolean ok);
261 
262  bool LoadURL(const PURL & url);
263  bool LoadURL(const PURL & url, const PTimeInterval & timeout, Options options = NoOptions);
264  bool LoadURL(const PURL & url, const PURL::LoadParams & params, Options options = NoOptions);
265 
266  protected:
267  PDECLARE_NOTIFIER(PTimer, PXML_HTTP, AutoReloadTimeout);
268  PDECLARE_NOTIFIER(PThread, PXML_HTTP, AutoReloadThread);
269 
275 };
276 #endif // P_HTTP
277 
279 
280 PARRAY(PXMLObjectArray, PXMLObject);
281 
282 class PXMLObject : public PObject {
283  PCLASSINFO(PXMLObject, PObject);
284  public:
286  : parent(par) { dirty = false; }
287 
289  { return parent; }
290 
291  PXMLObject * GetNextObject() const;
292 
293  void SetParent(PXMLElement * newParent)
294  {
295  PAssert(parent == NULL, "Cannot reparent PXMLElement");
296  parent = newParent;
297  }
298 
299  PString AsString() const;
300 
301  virtual void Output(ostream & strm, const PXMLBase & xml, int indent) const = 0;
302 
303  virtual PBoolean IsElement() const = 0;
304 
305  void SetDirty();
306  bool IsDirty() const { return dirty; }
307 
308  virtual PXMLObject * Clone(PXMLElement * parent) const = 0;
309 
310  protected:
312  bool dirty;
313 };
314 
316 
317 class PXMLData : public PXMLObject {
318  PCLASSINFO(PXMLData, PXMLObject);
319  public:
320  PXMLData(PXMLElement * parent, const PString & data);
321  PXMLData(PXMLElement * parent, const char * data, int len);
322 
323  PBoolean IsElement() const { return false; }
324 
325  void SetString(const PString & str, bool dirty = true);
326 
327  PString GetString() const { return value; }
328 
329  void Output(ostream & strm, const PXMLBase & xml, int indent) const;
330 
331  PXMLObject * Clone(PXMLElement * parent) const;
332 
333  protected:
335 };
336 
338 
339 class PXMLElement : public PXMLObject {
340  PCLASSINFO(PXMLElement, PXMLObject);
341  public:
342  PXMLElement(PXMLElement * parent, const char * name = NULL);
343  PXMLElement(PXMLElement * parent, const PString & name, const PString & data);
344 
345  PBoolean IsElement() const { return true; }
346 
347  void PrintOn(ostream & strm) const;
348  void Output(ostream & strm, const PXMLBase & xml, int indent) const;
349 
351  { return name; }
352 
358 
359  void SetName(const PString & v)
360  { name = v; }
361 
362  PINDEX GetSize() const
363  { return subObjects.GetSize(); }
364 
365  PXMLObject * AddSubObject(PXMLObject * elem, bool dirty = true);
366 
367  PXMLElement * AddChild (PXMLElement * elem, bool dirty = true);
368  PXMLData * AddChild (PXMLData * elem, bool dirty = true);
369 
370  PXMLElement * AddElement(const char * name);
371  PXMLElement * AddElement(const PString & name, const PString & data);
372  PXMLElement * AddElement(const PString & name, const PString & attrName, const PString & attrVal);
373 
374  void SetAttribute(const PCaselessString & key,
375  const PString & value,
376  bool setDirty = true);
377 
378  PString GetAttribute(const PCaselessString & key) const;
379  bool HasAttribute(const PCaselessString & key) const;
380  bool HasAttributes() const { return attributes.GetSize() > 0; }
381  const PStringToString & GetAttributes() const { return attributes; }
382 
383  PXMLElement * GetElement(const PCaselessString & name, const PCaselessString & attr, const PString & attrval) const;
384  PXMLElement * GetElement(const PCaselessString & name, PINDEX idx = 0) const;
385  PXMLObject * GetElement(PINDEX idx = 0) const;
386  bool RemoveElement(PINDEX idx);
387 
388  PINDEX FindObject(const PXMLObject * ptr) const;
389 
390  bool HasSubObjects() const
391  { return subObjects.GetSize() != 0; }
392 
393  PXMLObjectArray GetSubObjects() const
394  { return subObjects; }
395 
396  PXMLObject * GetSubObject(PINDEX idx = 0) const
397  { return GetElement(idx); }
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) const;
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:
435  PXMLSettings(Options options = NewLineAfterElement);
436 
437  void SetAttribute(const PCaselessString & section, const PString & key, const PString & value);
438 
439  PString GetAttribute(const PCaselessString & section, const PString & key) const;
440  bool HasAttribute(const PCaselessString & section, const PString & key) const;
441 
442  void ToConfig(PConfig & cfg) const;
443  void FromConfig(const PConfig & cfg);
444 };
445 
446 
448 
449 class PXMLParser : public PXMLBase
450 {
451  PCLASSINFO(PXMLParser, PXMLBase);
452  public:
453  PXMLParser(Options options = NoOptions);
454  ~PXMLParser();
455  bool Parse(const char * data, int dataLen, bool final);
456  void GetErrorInfo(PString & errorString, unsigned & errorCol, unsigned & errorLine);
457 
458  virtual void StartElement(const char * name, const char **attrs);
459  virtual void EndElement(const char * name);
460  virtual void AddCharacterData(const char * data, int len);
461  virtual void XmlDecl(const char * version, const char * encoding, int standAlone);
462  virtual void StartDocTypeDecl(const char * docTypeName,
463  const char * sysid,
464  const char * pubid,
465  int hasInternalSubSet);
466  virtual void EndDocTypeDecl();
467  virtual void StartNamespaceDeclHandler(const char * prefix, const char * uri);
468  virtual void EndNamespaceDeclHandler(const char * prefix);
469 
470  PString GetVersion() const { return version; }
471  PString GetEncoding() const { return encoding; }
472 
474 
475  PXMLElement * GetXMLTree() const;
476  PXMLElement * SetXMLTree(PXMLElement * newRoot);
477 
478  protected:
479  void * expat;
481  bool m_parsing;
487 };
488 
490 
492 {
493  PCLASSINFO(PXMLStreamParser, PXMLParser);
494  public:
496 
497  virtual void EndElement(const char * name);
498  virtual PXML * Read(PChannel * channel);
499 
500  protected:
502 };
503 
504 
505 #endif // P_EXPAT
506 
507 #endif // PTLIB_PXML_H
508 
509 
510 // End Of File ///////////////////////////////////////////////////////////////