PTLib Version 2.12.9

- Main Page
- Related Pages
- Namespaces
- Classes
- Files

- File List
- File Members

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 {
70 DEFAULT_MAX_ENTITY_LENGTH = 4096
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
77 enum StandAloneType {
78 UninitialisedStandAlone = -2,
79 UnknownStandAlone = -1,
80 NotStandAlone,
81 IsStandAlone
82 };
83
84 PXMLBase(Options opts = NoOptions);
85
86 void SetOptions(Options opts) { m_options = opts; }
87 Options GetOptions() const { return m_options; }
88
89 virtual PBoolean IsNoIndentElement(
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;
101 unsigned m_maxEntityLength;
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
132 PBoolean IsNoIndentElement(
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; }
146 PXMLElement * SetRootElement(PXMLElement * p);
147 PXMLElement * SetRootElement(const PString & documentType);
148 bool RemoveElement(PINDEX idx);
149
150 PCaselessString GetDocumentType() const;
151
152
153 enum ValidationOp {
154 EndOfValidationList,
155 DocType,
156 ElementName,
157 RequiredAttribute,
158 RequiredNonEmptyAttribute,
159 RequiredAttributeWithValue,
160 RequiredElement,
161 Subtree,
162 RequiredAttributeWithValueMatching,
163 RequiredElementWithBodyMatching,
164 OptionalElement,
165 OptionalAttribute,
166 OptionalNonEmptyAttribute,
167 OptionalAttributeWithValue,
168 OptionalAttributeWithValueMatching,
169 OptionalElementWithBodyMatching,
170 SetDefaultNamespace,
171 SetNamespace,
172
173 RequiredAttributeWithValueMatchingEx = RequiredAttributeWithValueMatching + 0x8000,
174 OptionalAttributeWithValueMatchingEx = OptionalAttributeWithValueMatching + 0x8000,
175 RequiredElementWithBodyMatchingEx = RequiredElementWithBodyMatching + 0x8000,
176 OptionalElementWithBodyMatchingEx = OptionalElementWithBodyMatching + 0x8000
177 };
178
179 struct ValidationContext {
180 PString m_defaultNameSpace;
181 PStringToString m_nameSpaces;
182 };
183
184 struct ValidationInfo {
185 ValidationOp m_op;
186 const char * m_name;
187
188 union {
189 const void * m_placeHolder;
190 const char * m_attributeValues;
191 ValidationInfo * m_subElement;
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
204 PString GetErrorString() const { return m_errorString; }
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:
222 PXMLElement * rootElement;
223 PMutex rootMutex;
224
225 bool loadFromFile;
226 PFilePath loadFilename;
227 PString version, encoding;
228 StandAloneType m_standAlone;
229
230 PStringStream m_errorString;
231 unsigned m_errorLine;
232 unsigned m_errorColumn;
233
234 PSortedStringList noIndentElements;
235
236 PString docType;
237 PString m_defaultNameSpace;
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();
258 PString GetAutoReloadStatus() { PWaitAndSignal m(autoLoadMutex); PString str = autoLoadError; return str; }
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
270 PTimer autoLoadTimer;
271 PURL autoloadURL;
272 PTimeInterval autoLoadWaitTime;
273 PMutex autoLoadMutex;
274 PString autoLoadError;
275 };
276 #endif // P_HTTP
277
279
280 PARRAY(PXMLObjectArray, PXMLObject);
281
282 class PXMLObject : public PObject {
283 PCLASSINFO(PXMLObject, PObject);
284 public:
285 PXMLObject(PXMLElement * par)
286 : parent(par) { dirty = false; }
287
288 PXMLElement * GetParent() const
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:
311 PXMLElement * parent;
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:
334 PString value;
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
350 PCaselessString GetName() const
351 { return name; }
352
357 PCaselessString GetPathName() const;
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;
413 PCaselessString PrependNamespace(const PCaselessString & name) const;
414 bool GetURIForNamespace(const PCaselessString & prefix, PCaselessString & uri) const;
415
416 protected:
417 PCaselessString name;
418 PStringToString attributes;
419 PXMLObjectArray subObjects;
420 bool dirty;
421 unsigned column;
422 unsigned lineNumber;
423 PStringToString m_nameSpaces;
424 PCaselessString m_defaultNamespace;
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
473 StandAloneType GetStandAlone() const { return m_standAlone; }
474
475 PXMLElement * GetXMLTree() const;
476 PXMLElement * SetXMLTree(PXMLElement * newRoot);
477
478 protected:
479 void * expat;
480 PXMLElement * rootElement;
481 bool m_parsing;
482 PXMLElement * currentElement;
483 PXMLData * lastElement;
484 PString version, encoding;
485 StandAloneType m_standAlone;
486 PStringToString m_tempNamespaceList;
487 };
488
490
491 class PXMLStreamParser : public PXMLParser
492 {
493 PCLASSINFO(PXMLStreamParser, PXMLParser);
494 public:
495 PXMLStreamParser();
496
497 virtual void EndElement(const char * name);
498 virtual PXML * Read(PChannel * channel);
499
500 protected:
501 PQueue<PXML> messages;
502 };
503
504
505 #endif // P_EXPAT
506
507 #endif // PTLIB_PXML_H
508
509
510 // End Of File ///////////////////////////////////////////////////////////////