6 * Portable Windows Library
8 * Copyright (c) 2002 Equivalence Pty. Ltd.
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/
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
20 * The Original Code is Portable Windows Library.
22 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
24 * Contributor(s): ______________________________________.
27 * Revision 1.23 2004/04/21 00:35:02 csoutheren
28 * Added a stream parser for protocols like XMPP where each child of the root is to be considered a separate document/message.
29 * Thanks to Federico Pinna and Reitek S.p.A.
31 * Revision 1.22 2003/04/27 23:54:13 craigs
32 * Removed deprecated options
34 * Revision 1.21 2003/03/31 07:41:50 craigs
35 * Fixed problem with accidental introduced dependency on expat.h
37 * Revision 1.20 2003/03/31 06:21:19 craigs
38 * Split the expat wrapper from the XML file handling to allow reuse of the parser
40 * Revision 1.19 2003/01/13 02:14:02 robertj
41 * Improved error logging for auto-loaded XML
43 * Revision 1.18 2002/12/16 06:38:24 robertj
44 * Added ability to specify certain elemets (by name) that are exempt from
45 * the indent formatting. Useful for XML/RPC where leading white space is
46 * not ignored by all servers.
48 * Revision 1.17 2002/11/26 05:53:57 craigs
49 * Added ability to auto-reload from URL
51 * Revision 1.16 2002/11/21 08:09:04 craigs
52 * Changed to not overwrite XML data if load fails
54 * Revision 1.15 2002/11/19 07:37:38 craigs
55 * Added locking functions and LoadURL function
57 * Revision 1.14 2002/11/06 22:47:24 robertj
58 * Fixed header comment (copyright etc)
70 #include <ptclib/http.h>
72 ////////////////////////////////////////////////////////////
77 class PXMLParser
: public PObject
79 PCLASSINFO(PXMLParser
, PObject
);
83 NewLineAfterElement
= 2,
84 NoIgnoreWhiteSpace
= 4, // ignored
85 CloseExtended
= 8, // ignored
89 PXMLParser(int options
= -1);
91 BOOL
Parse(const char * data
, int dataLen
, BOOL final
);
92 void GetErrorInfo(PString
& errorString
, PINDEX
& errorCol
, PINDEX
& errorLine
);
94 virtual void StartElement(const char * name
, const char **attrs
);
95 virtual void EndElement(const char * name
);
96 virtual void AddCharacterData(const char * data
, int len
);
97 virtual void XmlDecl(const char * version
, const char * encoding
, int standAlone
);
98 virtual void StartDocTypeDecl(const char * docTypeName
,
101 int hasInternalSubSet
);
102 virtual void EndDocTypeDecl();
103 virtual void StartNamespaceDeclHandler(const char * prefix
, const char * uri
);
104 virtual void EndNamespaceDeclHandler(const char * prefix
);
106 PString
GetVersion() const { return version
; }
107 PString
GetEncoding() const { return encoding
; }
108 BOOL
GetStandAlone() const { return standAlone
; }
110 PXMLElement
* GetXMLTree() const;
111 PXMLElement
* SetXMLTree(PXMLElement
* newRoot
);
116 PXMLElement
* rootElement
;
117 PXMLElement
* currentElement
;
118 PXMLData
* lastElement
;
119 PString version
, encoding
;
127 ////////////////////////////////////////////////////////////
129 class PXMLBase
: public PObject
132 PXMLBase(int _options
= -1)
133 : options(_options
) { if (options
< 0) options
= 0; }
135 void SetOptions(int _options
)
136 { options
= _options
; }
138 int GetOptions() const { return options
; }
140 virtual BOOL
IsNoIndentElement(
141 const PString
& /*elementName*/
152 class PXML
: public PXMLBase
154 PCLASSINFO(PXML
, PObject
);
159 const char * noIndentElements
= NULL
162 const PString
& data
,
164 const char * noIndentElements
= NULL
167 PXML(const PXML
& xml
);
171 BOOL
IsDirty() const;
173 BOOL
Load(const PString
& data
, int options
= -1);
175 BOOL
StartAutoReloadURL(const PURL
& url
,
176 const PTimeInterval
& timeout
,
177 const PTimeInterval
& refreshTime
,
179 BOOL
StopAutoReloadURL();
180 PString
GetAutoReloadStatus() { PWaitAndSignal
m(autoLoadMutex
); PString str
= autoLoadError
; return str
; }
182 virtual void OnAutoLoad(BOOL ok
);
184 BOOL
LoadURL(const PURL
& url
);
185 BOOL
LoadURL(const PURL
& url
, const PTimeInterval
& timeout
, int _options
= -1);
186 BOOL
LoadFile(const PFilePath
& fn
, int options
= -1);
188 virtual void OnLoaded() { }
190 BOOL
Save(int options
= -1);
191 BOOL
Save(PString
& data
, int options
= -1);
192 BOOL
SaveFile(const PFilePath
& fn
, int options
= -1);
196 BOOL
IsNoIndentElement(
197 const PString
& elementName
200 void PrintOn(ostream
& strm
) const;
202 PXMLElement
* GetElement(const PCaselessString
& name
, PINDEX idx
= 0) const;
203 PXMLElement
* GetElement(PINDEX idx
) const;
204 PINDEX
GetNumElements() const;
205 PXMLElement
* GetRootElement() const { return rootElement
; }
206 PXMLElement
* SetRootElement(PXMLElement
* p
);
207 PXMLElement
* SetRootElement(const PString
& documentType
);
208 BOOL
RemoveElement(PINDEX idx
);
210 PCaselessString
GetDocumentType() const;
212 PString
GetErrorString() const { return errorString
; }
213 PINDEX
GetErrorColumn() const { return errorCol
; }
214 PINDEX
GetErrorLine() const { return errorLine
; }
216 PMutex
& GetMutex() { return rootMutex
; }
218 PDECLARE_NOTIFIER(PTimer
, PXML
, AutoReloadTimeout
);
219 PDECLARE_NOTIFIER(PThread
, PXML
, AutoReloadThread
);
221 // static methods to create XML tags
222 static PString
CreateStartTag (const PString
& text
);
223 static PString
CreateEndTag (const PString
& text
);
224 static PString
CreateTagNoData (const PString
& text
);
225 static PString
CreateTag (const PString
& text
, const PString
& data
);
228 void Construct(int options
, const char * noIndentElements
);
229 PXMLElement
* rootElement
;
233 PFilePath loadFilename
;
234 PString version
, encoding
;
237 PTimer autoLoadTimer
;
239 PTimeInterval autoLoadWaitTime
;
240 PMutex autoLoadMutex
;
241 PString autoLoadError
;
247 PSortedStringList noIndentElements
;
250 ////////////////////////////////////////////////////////////
252 PARRAY(PXMLObjectArray
, PXMLObject
);
254 class PXMLObject
: public PObject
{
255 PCLASSINFO(PXMLObject
, PObject
);
257 PXMLObject(PXMLElement
* _parent
)
258 : parent(_parent
) { dirty
= FALSE
; }
260 PXMLElement
* GetParent()
263 PXMLObject
* GetNextObject();
265 void SetParent(PXMLElement
* newParent
)
267 PAssert(parent
== NULL
, "Cannot reparent PXMLElement");
271 virtual void Output(ostream
& strm
, const PXMLBase
& xml
, int indent
) const = 0;
273 virtual BOOL
IsElement() const = 0;
276 BOOL
IsDirty() const { return dirty
; }
278 virtual PXMLObject
* Clone(PXMLElement
* parent
) const = 0;
281 PXMLElement
* parent
;
285 ////////////////////////////////////////////////////////////
287 class PXMLData
: public PXMLObject
{
288 PCLASSINFO(PXMLData
, PXMLObject
);
290 PXMLData(PXMLElement
* _parent
, const PString
& data
);
291 PXMLData(PXMLElement
* _parent
, const char * data
, int len
);
293 BOOL
IsElement() const { return FALSE
; }
295 void SetString(const PString
& str
, BOOL dirty
= TRUE
);
297 PString
GetString() const { return value
; }
299 void Output(ostream
& strm
, const PXMLBase
& xml
, int indent
) const;
301 PXMLObject
* Clone(PXMLElement
* parent
) const;
307 ////////////////////////////////////////////////////////////
309 class PXMLElement
: public PXMLObject
{
310 PCLASSINFO(PXMLElement
, PXMLObject
);
312 PXMLElement(PXMLElement
* _parent
, const char * name
= NULL
);
313 PXMLElement(PXMLElement
* _parent
, const PString
& name
, const PString
& data
);
315 BOOL
IsElement() const { return TRUE
; }
317 void PrintOn(ostream
& strm
) const;
318 void Output(ostream
& strm
, const PXMLBase
& xml
, int indent
) const;
320 PCaselessString
GetName() const
323 void SetName(const PString
& v
)
326 PINDEX
GetSize() const
327 { return subObjects
.GetSize(); }
329 PXMLObject
* AddSubObject(PXMLObject
* elem
, BOOL dirty
= TRUE
);
331 PXMLElement
* AddChild (PXMLElement
* elem
, BOOL dirty
= TRUE
);
332 PXMLData
* AddChild (PXMLData
* elem
, BOOL dirty
= TRUE
);
334 void SetAttribute(const PCaselessString
& key
,
335 const PString
& value
,
336 BOOL setDirty
= TRUE
);
338 PString
GetAttribute(const PCaselessString
& key
) const;
339 PString
GetKeyAttribute(PINDEX idx
) const;
340 PString
GetDataAttribute(PINDEX idx
) const;
341 BOOL
HasAttribute(const PCaselessString
& key
);
342 BOOL
HasAttributes() const { return attributes
.GetSize() > 0; }
343 PINDEX
GetNumAttributes() const { return attributes
.GetSize(); }
345 PXMLElement
* GetElement(const PCaselessString
& name
, PINDEX idx
= 0) const;
346 PXMLObject
* GetElement(PINDEX idx
= 0) const;
347 BOOL
RemoveElement(PINDEX idx
);
349 PINDEX
FindObject(PXMLObject
* ptr
) const;
351 BOOL
HasSubObjects() const
352 { return subObjects
.GetSize() != 0; }
354 PXMLObjectArray
GetSubObjects() const
355 { return subObjects
; }
357 PString
GetData() const;
359 PXMLObject
* Clone(PXMLElement
* parent
) const;
362 PCaselessString name
;
363 PStringToString attributes
;
364 PXMLObjectArray subObjects
;
368 ////////////////////////////////////////////////////////////
370 class PXMLSettings
: public PXML
372 PCLASSINFO(PXMLSettings
, PXML
);
374 PXMLSettings(int options
= PXMLParser::NewLineAfterElement
);
375 PXMLSettings(const PString
& data
, int options
= PXMLParser::NewLineAfterElement
);
376 PXMLSettings(const PConfig
& data
, int options
= PXMLParser::NewLineAfterElement
);
378 BOOL
Load(const PString
& data
);
379 BOOL
LoadFile(const PFilePath
& fn
);
382 BOOL
Save(PString
& data
);
383 BOOL
SaveFile(const PFilePath
& fn
);
385 void SetAttribute(const PCaselessString
& section
, const PString
& key
, const PString
& value
);
387 PString
GetAttribute(const PCaselessString
& section
, const PString
& key
) const;
388 BOOL
HasAttribute(const PCaselessString
& section
, const PString
& key
) const;
390 void ToConfig(PConfig
& cfg
) const;
393 ////////////////////////////////////////////////////////////
395 class PXMLStreamParser
: public PXMLParser
397 PCLASSINFO(PXMLStreamParser
, PXMLParser
);
401 virtual void EndElement(const char * name
);
402 virtual PXML
* Read(PChannel
* channel
);
406 PQueue
<PXML
> messages
;