1 /*****************************************************************
2 |
3 |   Neptune - Xml Support
4 |
5 | Copyright (c) 2002-2008, Axiomatic Systems, LLC.
6 | All rights reserved.
7 |
8 | Redistribution and use in source and binary forms, with or without
9 | modification, are permitted provided that the following conditions are met:
10 |     * Redistributions of source code must retain the above copyright
11 |       notice, this list of conditions and the following disclaimer.
12 |     * Redistributions in binary form must reproduce the above copyright
13 |       notice, this list of conditions and the following disclaimer in the
14 |       documentation and/or other materials provided with the distribution.
15 |     * Neither the name of Axiomatic Systems nor the
16 |       names of its contributors may be used to endorse or promote products
17 |       derived from this software without specific prior written permission.
18 |
19 | THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
20 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 | DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
23 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 |
30  ****************************************************************/
31 
32 #ifndef _NPT_XML_H_
33 #define _NPT_XML_H_
34 
35 /*----------------------------------------------------------------------
36 |   includes
37 +---------------------------------------------------------------------*/
38 #include "NptTypes.h"
39 #include "NptList.h"
40 #include "NptStrings.h"
41 #include "NptStreams.h"
42 
43 /*----------------------------------------------------------------------
44 |   constants
45 +---------------------------------------------------------------------*/
46 const int NPT_ERROR_XML_INVALID_NESTING = NPT_ERROR_BASE_XML - 0;
47 const int NPT_ERROR_XML_TAG_MISMATCH    = NPT_ERROR_BASE_XML - 1;
48 const int NPT_ERROR_XML_NO_ROOT         = NPT_ERROR_BASE_XML - 2;
49 const int NPT_ERROR_XML_MULTIPLE_ROOTS  = NPT_ERROR_BASE_XML - 3;
50 
51 #define NPT_XML_ANY_NAMESPACE "*"
52 #define NPT_XML_NO_NAMESPACE  NULL
53 
54 /*----------------------------------------------------------------------
55 |   forward declarations
56 +---------------------------------------------------------------------*/
57 class NPT_XmlProcessor;
58 
59 /*----------------------------------------------------------------------
60 |   NPT_XmlAttribute
61 +---------------------------------------------------------------------*/
62 class NPT_XmlAttribute
63 {
64  public:
65     // methods
66     NPT_XmlAttribute(const char* name, const char* value);
NPT_XmlAttribute(const char * prefix,const char * name,const char * value)67     NPT_XmlAttribute(const char* prefix, const char* name, const char* value) :
68         m_Prefix(prefix), m_Name(name), m_Value(value) {}
GetPrefix()69     const NPT_String& GetPrefix() const { return m_Prefix; }
GetName()70     const NPT_String& GetName()   const { return m_Name;   }
GetValue()71     const NPT_String& GetValue()  const { return m_Value;  }
SetValue(const char * value)72     void              SetValue(const char* value) { m_Value = value; }
73 
74  private:
75     // members
76     NPT_String m_Prefix;
77     NPT_String m_Name;
78     NPT_String m_Value;
79 
NPT_XmlAttribute(const NPT_XmlAttribute & attribute)80     NPT_XmlAttribute(const NPT_XmlAttribute& attribute) :
81         m_Prefix(attribute.m_Prefix),
82         m_Name(attribute.m_Name),
83         m_Value(attribute.m_Value) {}
84     NPT_XmlAttribute& operator=(const NPT_XmlAttribute& a);
85 
86     // friends
87     friend class NPT_XmlAttributeFinder;
88     friend class NPT_XmlAttributeFinderWithPrefix;
89 };
90 
91 /*----------------------------------------------------------------------
92 |   NPT_XmlNamespaceMap
93 +---------------------------------------------------------------------*/
94 class NPT_XmlNamespaceMap
95 {
96 public:
97     // destructor
98     ~NPT_XmlNamespaceMap();
99 
100     // methods
101     NPT_Result        SetNamespaceUri(const char* prefix, const char* uri);
102     const NPT_String* GetNamespaceUri(const char* prefix);
103     const NPT_String* GetNamespacePrefix(const char* uri);
104 
105 private:
106     // types
107     class Entry {
108     public:
109         // constructor
Entry(const char * prefix,const char * uri)110         Entry(const char* prefix, const char* uri) :
111             m_Prefix(prefix), m_Uri(uri) {}
112 
113         // members
114         NPT_String m_Prefix;
115         NPT_String m_Uri;
116     };
117 
118     // members
119     NPT_List<Entry*> m_Entries;
120 
121     // friends
122     friend class NPT_XmlWriter;
123     friend class NPT_XmlNodeWriter;
124     friend class NPT_XmlNodeCanonicalWriter;
125 };
126 
127 /*----------------------------------------------------------------------
128 |   NPT_XmlNode
129 +---------------------------------------------------------------------*/
130 class NPT_XmlElementNode;
131 class NPT_XmlTextNode;
132 class NPT_XmlNode
133 {
134  public:
135     // types
136     typedef enum {
137         DOCUMENT,
138         ELEMENT,
139         TEXT
140     } Type;
141 
142     // methods
NPT_XmlNode(Type type)143     NPT_XmlNode(Type type) : m_Type(type), m_Parent(NULL) {}
~NPT_XmlNode()144     virtual     ~NPT_XmlNode() {}
GetType()145     Type         GetType() const { return m_Type; }
GetParent()146     NPT_XmlNode* GetParent() const { return m_Parent; }
147 
148     // type casting
AsElementNode()149     virtual NPT_XmlElementNode*       AsElementNode()       { return NULL; }
AsElementNode()150     virtual const NPT_XmlElementNode* AsElementNode() const { return NULL; }
AsTextNode()151     virtual NPT_XmlTextNode*          AsTextNode()          { return NULL; }
AsTextNode()152     virtual const NPT_XmlTextNode*    AsTextNode() const    { return NULL; }
153 
154  protected:
155     // methods
SetParent(NPT_XmlNode * parent)156     virtual void SetParent(NPT_XmlNode* parent) { m_Parent = parent; }
157 
158     // members
159     Type         m_Type;
160     NPT_XmlNode* m_Parent;
161 
162     // friends
163     friend class NPT_XmlNodeFinder;
164     friend class NPT_XmlSerializer;
165     friend class NPT_XmlWriter;
166     friend class NPT_XmlElementNode; // to allow access to SetParent()
167 };
168 
169 /*----------------------------------------------------------------------
170 |   NPT_XmlElementNode
171 +---------------------------------------------------------------------*/
172 class NPT_XmlElementNode : public NPT_XmlNode
173 {
174  public:
175     // methods
176                             NPT_XmlElementNode(const char* tag);
177                             NPT_XmlElementNode(const char* prefix, const char* tag);
178     virtual                ~NPT_XmlElementNode();
GetChildren()179     NPT_List<NPT_XmlNode*>& GetChildren() { return m_Children; }
180     const NPT_List<NPT_XmlNode*>&
GetChildren()181                             GetChildren() const { return m_Children; }
182     NPT_XmlElementNode*     GetChild(const char* tag,
183                                      const char* namespc = NPT_XML_NO_NAMESPACE,
184                                      NPT_Ordinal n=0) const;
185     NPT_Result              AddChild(NPT_XmlNode* child);
186     NPT_Result              SetAttribute(const char* prefix,
187                                          const char* name,
188                                          const char* value);
189     NPT_Result              SetAttribute(const char* name,
190                                          const char* value);
191     NPT_Result              AddText(const char* text);
192     NPT_List<NPT_XmlAttribute*>&
GetAttributes()193                             GetAttributes() { return m_Attributes; }
194     const NPT_List<NPT_XmlAttribute*>&
GetAttributes()195                             GetAttributes() const { return m_Attributes; }
196     const NPT_String*       GetAttribute(const char* name,
197                                          const char* namespc = NPT_XML_NO_NAMESPACE) const;
GetPrefix()198     const NPT_String&       GetPrefix() const { return m_Prefix; }
GetTag()199     const NPT_String&       GetTag()    const { return m_Tag;    }
200     const NPT_String*       GetText(NPT_Ordinal n=0) const;
201 
202     // bring all the namespace definitions used in this element of one of its descendants
203     // into the namespace map of this element so that it may be serialized as a
204     // standalone element without any prefixes with undefined namespace uris
205     NPT_Result              MakeStandalone();
206 
207     // namespace methods
208     const NPT_String* GetNamespace() const;
209     NPT_Result        SetNamespaceUri(const char* prefix, const char* uri);
210     const NPT_String* GetNamespaceUri(const char* prefix) const;
211     const NPT_String* GetNamespacePrefix(const char* uri) const;
212 
213     // type casting
AsElementNode()214     NPT_XmlElementNode*       AsElementNode()       { return this; }
AsElementNode()215     const NPT_XmlElementNode* AsElementNode() const { return this; }
216 
217 protected:
218     // methods
219     void SetParent(NPT_XmlNode* parent);
220     void SetNamespaceParent(NPT_XmlElementNode* parent);
221     void RelinkNamespaceMaps();
222 
223     NPT_Result AddAttribute(const char* name, const char* value);
224 
225     // members
226     NPT_String                  m_Prefix;
227     NPT_String                  m_Tag;
228     NPT_List<NPT_XmlNode*>      m_Children;
229     NPT_List<NPT_XmlAttribute*> m_Attributes;
230     NPT_XmlNamespaceMap*        m_NamespaceMap;
231     NPT_XmlElementNode*         m_NamespaceParent;
232 
233     // friends
234     friend class NPT_XmlTagFinder;
235     friend class NPT_XmlSerializer;
236     friend class NPT_XmlWriter;
237     friend class NPT_XmlNodeWriter;
238     friend class NPT_XmlNodeCanonicalWriter;
239     friend class NPT_XmlParser;
240     friend class NPT_XmlProcessor;
241     friend class NPT_XmlNamespaceCollapser;
242 };
243 
244 /*----------------------------------------------------------------------
245 |   NPT_XmlTextNode
246 +---------------------------------------------------------------------*/
247 class NPT_XmlTextNode : public NPT_XmlNode
248 {
249  public:
250     // types
251     typedef enum {
252         CHARACTER_DATA,
253         IGNORABLE_WHITESPACE,
254         CDATA_SECTION,
255         ENTITY_REFERENCE,
256         COMMENT
257     } TokenType;
258 
259     // constructor
260     NPT_XmlTextNode(TokenType token_type, const char* text);
261 
262     // methods
GetString()263     const NPT_String& GetString() const { return m_Text; }
264 
265     // type casting
AsTextNode()266     NPT_XmlTextNode*       AsTextNode()       { return this; }
AsTextNode()267     const NPT_XmlTextNode* AsTextNode() const { return this; }
268 
269  private:
270     // members
271 //    TokenType  m_TokenType;
272     NPT_String m_Text;
273 };
274 
275 /*----------------------------------------------------------------------
276 |   NPT_XmlParser
277 +---------------------------------------------------------------------*/
278 class NPT_XmlParser
279 {
280  public:
281     // methods
282              NPT_XmlParser(bool keep_whitespace = true);
283     virtual ~NPT_XmlParser();
284     virtual  NPT_Result Parse(const char*   xml,
285                               NPT_XmlNode*& tree,
286                               bool          incremental=false);
287     virtual  NPT_Result Parse(const char*   xml,
288                               NPT_Size      size,
289                               NPT_XmlNode*& tree,
290                               bool          incremental=false);
291     virtual  NPT_Result Parse(NPT_InputStream& stream,
292                               NPT_XmlNode*&    tree,
293                               bool             incremental=false);
294     virtual  NPT_Result Parse(NPT_InputStream& stream,
295                               NPT_Size&        size,
296                               NPT_XmlNode*&    tree,
297                               bool             incremental=false);
298 
299  protected:
300     // NPT_XmlHandler methods
301     NPT_Result OnStartElement(const char* name);
302     NPT_Result OnElementAttribute(const char* name, const char* value);
303     NPT_Result OnEndElement(const char* name);
304     NPT_Result OnCharacterData(const char* data, unsigned long size);
305     void       RemoveIgnorableWhitespace();
306 
307     // members
308     NPT_XmlProcessor*   m_Processor;
309     NPT_XmlElementNode* m_Root;
310     NPT_XmlElementNode* m_CurrentElement;
311     bool                m_KeepWhitespace;
312 
313 private:
314     void Reset();
315 
316     // friends
317     friend class NPT_XmlProcessor;
318 };
319 
320 /*----------------------------------------------------------------------
321 |   NPT_XmlSerializer
322 +---------------------------------------------------------------------*/
323 class NPT_XmlSerializer
324 {
325 public:
326     // methods
327                        NPT_XmlSerializer(NPT_OutputStream* output,
328                                          NPT_Cardinal      indentation = 0,
329                                          bool              shrink_empty_elements = true,
330                                          bool              add_xml_decl = false);
331     virtual           ~NPT_XmlSerializer();
332     virtual NPT_Result StartDocument();
333     virtual NPT_Result EndDocument();
334     virtual NPT_Result StartElement(const char* prefix, const char* name);
335     virtual NPT_Result EndElement(const char* prefix, const char* name);
336     virtual NPT_Result Attribute(const char* prefix, const char* name, const char* value);
337     virtual NPT_Result Text(const char* text);
338     virtual NPT_Result CdataSection(const char* data);
339     virtual NPT_Result Comment(const char* comment);
340 
341 protected:
342     // methods
343     void       EscapeChar(unsigned char c, char* text);
344     NPT_Result ProcessPending();
345     NPT_Result OutputEscapedString(const char* text, bool attribute);
346     void       OutputIndentation(bool start);
347 
348     // members
349     NPT_OutputStream* m_Output;
350     bool              m_ElementPending;
351     NPT_Cardinal      m_Depth;
352     NPT_Cardinal      m_Indentation;
353     NPT_String        m_IndentationPrefix;
354     bool              m_ElementHasText;
355     bool              m_ShrinkEmptyElements;
356     bool              m_AddXmlDecl;
357 };
358 
359 /*----------------------------------------------------------------------
360 |   NPT_XmlWriter
361 +---------------------------------------------------------------------*/
362 class NPT_XmlWriter
363 {
364 public:
365     // constructor
m_Indentation(indentation)366     explicit NPT_XmlWriter(NPT_Cardinal indentation = 0) : m_Indentation(indentation) {}
367 
368     // methods
369     NPT_Result Serialize(NPT_XmlNode&      node,
370                          NPT_OutputStream& stream,
371                          bool              add_xml_decl = false);
372 
373 private:
374     // members
375     NPT_Cardinal m_Indentation;
376 };
377 
378 /*----------------------------------------------------------------------
379 |   NPT_XmlCanonicalizer
380 +---------------------------------------------------------------------*/
381 class NPT_XmlCanonicalizer
382 {
383 public:
384     // methods
385     NPT_Result Serialize(NPT_XmlNode&      node,
386                          NPT_OutputStream& stream,
387                          bool              add_xml_decl = false);
388 };
389 
390 #endif // _NPT_XML_H_
391