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.22 2003/04/27 23:54:13 craigs
28 * Removed deprecated options
30 * Revision 1.21 2003/03/31 07:41:50 craigs
31 * Fixed problem with accidental introduced dependency on expat.h
33 * Revision 1.20 2003/03/31 06:21:19 craigs
34 * Split the expat wrapper from the XML file handling to allow reuse of the parser
36 * Revision 1.19 2003/01/13 02:14:02 robertj
37 * Improved error logging for auto-loaded XML
39 * Revision 1.18 2002/12/16 06:38:24 robertj
40 * Added ability to specify certain elemets (by name) that are exempt from
41 * the indent formatting. Useful for XML/RPC where leading white space is
42 * not ignored by all servers.
44 * Revision 1.17 2002/11/26 05:53:57 craigs
45 * Added ability to auto-reload from URL
47 * Revision 1.16 2002/11/21 08:09:04 craigs
48 * Changed to not overwrite XML data if load fails
50 * Revision 1.15 2002/11/19 07:37:38 craigs
51 * Added locking functions and LoadURL function
53 * Revision 1.14 2002/11/06 22:47:24 robertj
54 * Fixed header comment (copyright etc)
66 #include <ptclib/http.h>
68 ////////////////////////////////////////////////////////////
73 class PXMLParser
: public PObject
75 PCLASSINFO(PXMLParser
, PObject
);
79 NewLineAfterElement
= 2,
80 NoIgnoreWhiteSpace
= 4, // ignored
81 CloseExtended
= 8, // ignored
85 PXMLParser(int options
= -1);
87 BOOL
Parse(const char * data
, int dataLen
, BOOL final
);
88 void GetErrorInfo(PString
& errorString
, PINDEX
& errorCol
, PINDEX
& errorLine
);
90 virtual void StartElement(const char * name
, const char **attrs
);
91 virtual void EndElement(const char * name
);
92 virtual void AddCharacterData(const char * data
, int len
);
93 virtual void XmlDecl(const char * version
, const char * encoding
, int standAlone
);
94 virtual void StartDocTypeDecl(const char * docTypeName
,
97 int hasInternalSubSet
);
98 virtual void EndDocTypeDecl();
99 virtual void StartNamespaceDeclHandler(const char * prefix
, const char * uri
);
100 virtual void EndNamespaceDeclHandler(const char * prefix
);
102 PString
GetVersion() const { return version
; }
103 PString
GetEncoding() const { return encoding
; }
104 BOOL
GetStandAlone() const { return standAlone
; }
106 PXMLElement
* GetXMLTree() const;
107 PXMLElement
* SetXMLTree(PXMLElement
* newRoot
);
112 PXMLElement
* rootElement
;
113 PXMLElement
* currentElement
;
114 PXMLData
* lastElement
;
115 PString version
, encoding
;
123 ////////////////////////////////////////////////////////////
125 class PXMLBase
: public PObject
128 PXMLBase(int _options
= -1)
129 : options(_options
) { if (options
< 0) options
= 0; }
131 void SetOptions(int _options
)
132 { options
= _options
; }
134 int GetOptions() const { return options
; }
136 virtual BOOL
IsNoIndentElement(
137 const PString
& /*elementName*/
148 class PXML
: public PXMLBase
150 PCLASSINFO(PXML
, PObject
);
155 const char * noIndentElements
= NULL
158 const PString
& data
,
160 const char * noIndentElements
= NULL
163 PXML(const PXML
& xml
);
167 BOOL
IsDirty() const;
169 BOOL
Load(const PString
& data
, int options
= -1);
171 BOOL
StartAutoReloadURL(const PURL
& url
,
172 const PTimeInterval
& timeout
,
173 const PTimeInterval
& refreshTime
,
175 BOOL
StopAutoReloadURL();
176 PString
GetAutoReloadStatus() { PWaitAndSignal
m(autoLoadMutex
); PString str
= autoLoadError
; return str
; }
178 virtual void OnAutoLoad(BOOL ok
);
180 BOOL
LoadURL(const PURL
& url
);
181 BOOL
LoadURL(const PURL
& url
, const PTimeInterval
& timeout
, int _options
= -1);
182 BOOL
LoadFile(const PFilePath
& fn
, int options
= -1);
184 virtual void OnLoaded() { }
186 BOOL
Save(int options
= -1);
187 BOOL
Save(PString
& data
, int options
= -1);
188 BOOL
SaveFile(const PFilePath
& fn
, int options
= -1);
192 BOOL
IsNoIndentElement(
193 const PString
& elementName
196 void PrintOn(ostream
& strm
) const;
198 PXMLElement
* GetElement(const PCaselessString
& name
, PINDEX idx
= 0) const;
199 PXMLElement
* GetElement(PINDEX idx
) const;
200 PINDEX
GetNumElements() const;
201 PXMLElement
* GetRootElement() const { return rootElement
; }
202 PXMLElement
* SetRootElement(PXMLElement
* p
);
203 PXMLElement
* SetRootElement(const PString
& documentType
);
204 BOOL
RemoveElement(PINDEX idx
);
206 PCaselessString
GetDocumentType() const;
208 PString
GetErrorString() const { return errorString
; }
209 PINDEX
GetErrorColumn() const { return errorCol
; }
210 PINDEX
GetErrorLine() const { return errorLine
; }
212 PMutex
& GetMutex() { return rootMutex
; }
214 PDECLARE_NOTIFIER(PTimer
, PXML
, AutoReloadTimeout
);
215 PDECLARE_NOTIFIER(PThread
, PXML
, AutoReloadThread
);
217 // static methods to create XML tags
218 static PString
CreateStartTag (const PString
& text
);
219 static PString
CreateEndTag (const PString
& text
);
220 static PString
CreateTagNoData (const PString
& text
);
221 static PString
CreateTag (const PString
& text
, const PString
& data
);
224 void Construct(int options
, const char * noIndentElements
);
225 PXMLElement
* rootElement
;
229 PFilePath loadFilename
;
230 PString version
, encoding
;
233 PTimer autoLoadTimer
;
235 PTimeInterval autoLoadWaitTime
;
236 PMutex autoLoadMutex
;
237 PString autoLoadError
;
243 PSortedStringList noIndentElements
;
246 ////////////////////////////////////////////////////////////
248 PARRAY(PXMLObjectArray
, PXMLObject
);
250 class PXMLObject
: public PObject
{
251 PCLASSINFO(PXMLObject
, PObject
);
253 PXMLObject(PXMLElement
* _parent
)
254 : parent(_parent
) { dirty
= FALSE
; }
256 PXMLElement
* GetParent()
259 PXMLObject
* GetNextObject();
261 void SetParent(PXMLElement
* newParent
)
263 PAssert(parent
== NULL
, "Cannot reparent PXMLElement");
267 virtual void Output(ostream
& strm
, const PXMLBase
& xml
, int indent
) const = 0;
269 virtual BOOL
IsElement() const = 0;
272 BOOL
IsDirty() const { return dirty
; }
274 virtual PXMLObject
* Clone(PXMLElement
* parent
) const = 0;
277 PXMLElement
* parent
;
281 ////////////////////////////////////////////////////////////
283 class PXMLData
: public PXMLObject
{
284 PCLASSINFO(PXMLData
, PXMLObject
);
286 PXMLData(PXMLElement
* _parent
, const PString
& data
);
287 PXMLData(PXMLElement
* _parent
, const char * data
, int len
);
289 BOOL
IsElement() const { return FALSE
; }
291 void SetString(const PString
& str
, BOOL dirty
= TRUE
);
293 PString
GetString() const { return value
; }
295 void Output(ostream
& strm
, const PXMLBase
& xml
, int indent
) const;
297 PXMLObject
* Clone(PXMLElement
* parent
) const;
303 ////////////////////////////////////////////////////////////
305 class PXMLElement
: public PXMLObject
{
306 PCLASSINFO(PXMLElement
, PXMLObject
);
308 PXMLElement(PXMLElement
* _parent
, const char * name
= NULL
);
309 PXMLElement(PXMLElement
* _parent
, const PString
& name
, const PString
& data
);
311 BOOL
IsElement() const { return TRUE
; }
313 void PrintOn(ostream
& strm
) const;
314 void Output(ostream
& strm
, const PXMLBase
& xml
, int indent
) const;
316 PCaselessString
GetName() const
319 void SetName(const PString
& v
)
322 PINDEX
GetSize() const
323 { return subObjects
.GetSize(); }
325 PXMLObject
* AddSubObject(PXMLObject
* elem
, BOOL dirty
= TRUE
);
327 PXMLElement
* AddChild (PXMLElement
* elem
, BOOL dirty
= TRUE
);
328 PXMLData
* AddChild (PXMLData
* elem
, BOOL dirty
= TRUE
);
330 void SetAttribute(const PCaselessString
& key
,
331 const PString
& value
,
332 BOOL setDirty
= TRUE
);
334 PString
GetAttribute(const PCaselessString
& key
) const;
335 PString
GetKeyAttribute(PINDEX idx
) const;
336 PString
GetDataAttribute(PINDEX idx
) const;
337 BOOL
HasAttribute(const PCaselessString
& key
);
338 BOOL
HasAttributes() const { return attributes
.GetSize() > 0; }
339 PINDEX
GetNumAttributes() const { return attributes
.GetSize(); }
341 PXMLElement
* GetElement(const PCaselessString
& name
, PINDEX idx
= 0) const;
342 PXMLObject
* GetElement(PINDEX idx
= 0) const;
343 BOOL
RemoveElement(PINDEX idx
);
345 PINDEX
FindObject(PXMLObject
* ptr
) const;
347 BOOL
HasSubObjects() const
348 { return subObjects
.GetSize() != 0; }
350 PXMLObjectArray
GetSubObjects() const
351 { return subObjects
; }
353 PString
GetData() const;
355 PXMLObject
* Clone(PXMLElement
* parent
) const;
358 PCaselessString name
;
359 PStringToString attributes
;
360 PXMLObjectArray subObjects
;
364 ////////////////////////////////////////////////////////////
366 class PXMLSettings
: public PXML
368 PCLASSINFO(PXMLSettings
, PXML
);
370 PXMLSettings(int options
= PXMLParser::NewLineAfterElement
);
371 PXMLSettings(const PString
& data
, int options
= PXMLParser::NewLineAfterElement
);
372 PXMLSettings(const PConfig
& data
, int options
= PXMLParser::NewLineAfterElement
);
374 BOOL
Load(const PString
& data
);
375 BOOL
LoadFile(const PFilePath
& fn
);
378 BOOL
Save(PString
& data
);
379 BOOL
SaveFile(const PFilePath
& fn
);
381 void SetAttribute(const PCaselessString
& section
, const PString
& key
, const PString
& value
);
383 PString
GetAttribute(const PCaselessString
& section
, const PString
& key
) const;
384 BOOL
HasAttribute(const PCaselessString
& section
, const PString
& key
) const;
386 void ToConfig(PConfig
& cfg
) const;