NptXml.h

00001 /*****************************************************************
00002 |
00003 |   Neptune - Xml Support
00004 |
00005 |   (c) 2001-2006 Gilles Boccon-Gibod
00006 |   Author: Gilles Boccon-Gibod (bok@bok.net)
00007 |
00008  ****************************************************************/
00009 
00010 #ifndef _NPT_XML_H_
00011 #define _NPT_XML_H_
00012 
00013 /*----------------------------------------------------------------------
00014 |   includes
00015 +---------------------------------------------------------------------*/
00016 #include "NptTypes.h"
00017 #include "NptList.h"
00018 #include "NptStrings.h"
00019 #include "NptStreams.h"
00020 
00021 /*----------------------------------------------------------------------
00022 |   constants
00023 +---------------------------------------------------------------------*/
00024 const int NPT_ERROR_XML_INVALID_NESTING = NPT_ERROR_BASE_XML - 0;
00025 const int NPT_ERROR_XML_TAG_MISMATCH    = NPT_ERROR_BASE_XML - 1;
00026 
00027 #define NPT_XML_ANY_NAMESPACE "*"
00028 #define NPT_XML_NO_NAMESPACE  NULL
00029 
00030 /*----------------------------------------------------------------------
00031 |   forward declarations
00032 +---------------------------------------------------------------------*/
00033 class NPT_XmlProcessor;
00034 
00035 /*----------------------------------------------------------------------
00036 |   NPT_XmlAttribute
00037 +---------------------------------------------------------------------*/
00038 class NPT_XmlAttribute
00039 {
00040  public:
00041     // methods
00042     NPT_XmlAttribute(const char* name, const char* value);
00043     NPT_XmlAttribute(const char* prefix, const char* name, const char* value) :
00044         m_Prefix(prefix), m_Name(name), m_Value(value) {}
00045     const NPT_String& GetPrefix() const { return m_Prefix; }
00046     const NPT_String& GetName()   const { return m_Name;   }
00047     const NPT_String& GetValue()  const { return m_Value;  }
00048     void              SetValue(const char* value) { m_Value = value; }
00049 
00050  private:
00051     // members
00052     NPT_String m_Prefix;
00053     NPT_String m_Name;
00054     NPT_String m_Value;
00055 
00056     NPT_XmlAttribute(const NPT_XmlAttribute& attribute) :
00057         m_Prefix(attribute.m_Prefix), 
00058         m_Name(attribute.m_Name), 
00059         m_Value(attribute.m_Value) {}
00060     NPT_XmlAttribute& operator=(const NPT_XmlAttribute& a);
00061 
00062     // friends
00063     friend class NPT_XmlAttributeFinder;
00064     friend class NPT_XmlAttributeFinderWithPrefix;
00065 };
00066 
00067 /*----------------------------------------------------------------------
00068 |   NPT_XmlNamespaceMap
00069 +---------------------------------------------------------------------*/
00070 class NPT_XmlNamespaceMap
00071 {
00072 public:
00073     // destructor
00074     ~NPT_XmlNamespaceMap();
00075 
00076     // methods   
00077     NPT_Result        SetNamespaceUri(const char* prefix, const char* uri);
00078     const NPT_String* GetNamespaceUri(const char* prefix);
00079     const NPT_String* GetNamespacePrefix(const char* uri);
00080 
00081 private:
00082     // types
00083     class Entry {
00084     public:
00085         // constructor
00086         Entry(const char* prefix, const char* uri) : 
00087             m_Prefix(prefix), m_Uri(uri) {}
00088 
00089         // members
00090         NPT_String m_Prefix;
00091         NPT_String m_Uri;
00092     };
00093 
00094     // members
00095     NPT_List<Entry*> m_Entries;
00096 
00097     // friends
00098     friend class NPT_XmlWriter;
00099     friend class NPT_XmlNodeWriter;
00100     friend class NPT_XmlNodeCanonicalWriter;
00101 };
00102 
00103 /*----------------------------------------------------------------------
00104 |   NPT_XmlNode
00105 +---------------------------------------------------------------------*/
00106 class NPT_XmlElementNode;
00107 class NPT_XmlTextNode;
00108 class NPT_XmlNode
00109 {
00110  public:
00111     // types
00112     typedef enum {
00113         DOCUMENT,
00114         ELEMENT,
00115         TEXT
00116     } Type;
00117 
00118     // methods
00119     NPT_XmlNode(Type type) : m_Type(type), m_Parent(NULL) {}
00120     virtual     ~NPT_XmlNode() {}
00121     Type         GetType() const { return m_Type; }
00122     NPT_XmlNode* GetParent() const { return m_Parent; }
00123 
00124     // type casting
00125     virtual NPT_XmlElementNode*       AsElementNode()       { return NULL; }
00126     virtual const NPT_XmlElementNode* AsElementNode() const { return NULL; }
00127     virtual NPT_XmlTextNode*          AsTextNode()          { return NULL; }
00128     virtual const NPT_XmlTextNode*    AsTextNode() const    { return NULL; }
00129 
00130  protected:
00131     // methods
00132     virtual void SetParent(NPT_XmlNode* parent) { m_Parent = parent; }
00133 
00134     // members  
00135     Type         m_Type;
00136     NPT_XmlNode* m_Parent;
00137 
00138     // friends
00139     friend class NPT_XmlNodeFinder;
00140     friend class NPT_XmlSerializer;
00141     friend class NPT_XmlWriter;
00142     friend class NPT_XmlElementNode; // to allow access to SetParent()
00143 };
00144 
00145 /*----------------------------------------------------------------------
00146 |   NPT_XmlElementNode
00147 +---------------------------------------------------------------------*/
00148 class NPT_XmlElementNode : public NPT_XmlNode
00149 {
00150  public:
00151     // methods
00152                             NPT_XmlElementNode(const char* tag);
00153                             NPT_XmlElementNode(const char* prefix, const char* tag);
00154     virtual                ~NPT_XmlElementNode();
00155     NPT_List<NPT_XmlNode*>& GetChildren() { return m_Children; }
00156     const NPT_List<NPT_XmlNode*>& 
00157                             GetChildren() const { return m_Children; }
00158     NPT_XmlElementNode*     GetChild(const char* tag, 
00159                                      const char* namespc = NPT_XML_NO_NAMESPACE,
00160                                      NPT_Ordinal n=0) const;
00161     NPT_Result              AddChild(NPT_XmlNode* child);
00162     NPT_Result              SetAttribute(const char* prefix,
00163                                          const char* name, 
00164                                          const char* value);
00165     NPT_Result              SetAttribute(const char* name, 
00166                                          const char* value);
00167     NPT_Result              AddText(const char* text); 
00168     NPT_List<NPT_XmlAttribute*>& 
00169                             GetAttributes() { return m_Attributes; }
00170     const NPT_List<NPT_XmlAttribute*>&
00171                             GetAttributes() const { return m_Attributes; }
00172     const NPT_String*       GetAttribute(const char* name,
00173                                          const char* namespc = NPT_XML_NO_NAMESPACE) const;
00174     const NPT_String&       GetPrefix() const { return m_Prefix; }
00175     const NPT_String&       GetTag()    const { return m_Tag;    }
00176     const NPT_String*       GetText(NPT_Ordinal n=0) const;
00177 
00178     // bring all the namespace definitions used in this element of one of its descendants
00179     // into the namespace map of this element so that it may be serialized as a
00180     // standalone element without any prefixes with undefined namespace uris
00181     NPT_Result              MakeStandalone();
00182 
00183     // namespace methods   
00184     const NPT_String* GetNamespace() const;
00185     NPT_Result        SetNamespaceUri(const char* prefix, const char* uri);
00186     const NPT_String* GetNamespaceUri(const char* prefix) const;
00187     const NPT_String* GetNamespacePrefix(const char* uri) const;
00188 
00189     // type casting
00190     NPT_XmlElementNode*       AsElementNode()       { return this; }
00191     const NPT_XmlElementNode* AsElementNode() const { return this; }
00192 
00193 protected:
00194     // methods
00195     void SetParent(NPT_XmlNode* parent);
00196     void SetNamespaceParent(NPT_XmlElementNode* parent);
00197     void RelinkNamespaceMaps();
00198 
00199     NPT_Result AddAttribute(const char* name, const char* value);
00200 
00201     // members  
00202     NPT_String                  m_Prefix;
00203     NPT_String                  m_Tag;
00204     NPT_List<NPT_XmlNode*>      m_Children;
00205     NPT_List<NPT_XmlAttribute*> m_Attributes;
00206     NPT_XmlNamespaceMap*        m_NamespaceMap;
00207     NPT_XmlElementNode*         m_NamespaceParent;
00208 
00209     // friends
00210     friend class NPT_XmlTagFinder;
00211     friend class NPT_XmlSerializer;
00212     friend class NPT_XmlWriter;
00213     friend class NPT_XmlNodeWriter;
00214     friend class NPT_XmlNodeCanonicalWriter;
00215     friend class NPT_XmlParser;
00216     friend class NPT_XmlProcessor;
00217     friend class NPT_XmlNamespaceCollapser;
00218 };
00219 
00220 /*----------------------------------------------------------------------
00221 |   NPT_XmlTextNode
00222 +---------------------------------------------------------------------*/
00223 class NPT_XmlTextNode : public NPT_XmlNode
00224 {
00225  public:
00226     // types
00227     typedef enum {
00228         CHARACTER_DATA,
00229         IGNORABLE_WHITESPACE,
00230         CDATA_SECTION,
00231         ENTITY_REFERENCE,
00232         COMMENT
00233     } TokenType;
00234 
00235     // constructor
00236     NPT_XmlTextNode(TokenType token_type, const char* text);
00237 
00238     // methods
00239     const NPT_String& GetString() const { return m_Text; }
00240 
00241     // type casting
00242     NPT_XmlTextNode*       AsTextNode()       { return this; }
00243     const NPT_XmlTextNode* AsTextNode() const { return this; }
00244 
00245  private:
00246     // members  
00247     TokenType  m_TokenType;
00248     NPT_String m_Text;
00249 };
00250 
00251 /*----------------------------------------------------------------------
00252 |   NPT_XmlParser
00253 +---------------------------------------------------------------------*/
00254 class NPT_XmlParser
00255 {
00256  public:
00257     // methods
00258              NPT_XmlParser(bool keep_whitespace = true);
00259     virtual ~NPT_XmlParser();
00260     virtual  NPT_Result Parse(const char*   xml, 
00261                               NPT_XmlNode*& tree,
00262                               bool          incremental=false);
00263     virtual  NPT_Result Parse(const char*   xml, 
00264                               NPT_Size      size,
00265                               NPT_XmlNode*& tree,
00266                               bool          incremental=false);
00267     virtual  NPT_Result Parse(NPT_InputStream& stream, 
00268                               NPT_XmlNode*&    tree,
00269                               bool             incremental=false);
00270     virtual  NPT_Result Parse(NPT_InputStream& stream, 
00271                               NPT_Size&        size,
00272                               NPT_XmlNode*&    tree,
00273                               bool             incremental=false);
00274     
00275  protected:
00276     // NPT_XmlHandler methods
00277     NPT_Result OnStartElement(const char* name);
00278     NPT_Result OnElementAttribute(const char* name, const char* value);
00279     NPT_Result OnEndElement(const char* name);
00280     NPT_Result OnCharacterData(const char* data, unsigned long size);
00281     void       RemoveIgnorableWhitespace();
00282 
00283     // members
00284     NPT_XmlProcessor*   m_Processor;
00285     NPT_XmlElementNode* m_Tree;
00286     NPT_XmlElementNode* m_CurrentElement;
00287     bool                m_KeepWhitespace;
00288 
00289     // friends
00290     friend class NPT_XmlProcessor;
00291 };
00292 
00293 /*----------------------------------------------------------------------
00294 |   NPT_XmlSerializer
00295 +---------------------------------------------------------------------*/
00296 class NPT_XmlSerializer
00297 {
00298 public:
00299     // methods
00300                        NPT_XmlSerializer(NPT_OutputStream* output,
00301                                          NPT_Cardinal      indentation = 0,
00302                                          bool              shrink_empty_elements = true);
00303     virtual           ~NPT_XmlSerializer();
00304     virtual NPT_Result StartDocument();
00305     virtual NPT_Result EndDocument();
00306     virtual NPT_Result StartElement(const char* prefix, const char* name);
00307     virtual NPT_Result EndElement(const char* prefix, const char* name);
00308     virtual NPT_Result Attribute(const char* prefix, const char* name, const char* value);
00309     virtual NPT_Result Text(const char* text);
00310     virtual NPT_Result CdataSection(const char* data);
00311     virtual NPT_Result Comment(const char* comment);
00312 
00313 protected:
00314     // methods
00315     void       EscapeChar(unsigned char c, char* text);
00316     NPT_Result ProcessPending();
00317     NPT_Result OutputEscapedString(const char* text, bool attribute);
00318     void       OutputIndentation(bool start);
00319 
00320     // members
00321     NPT_OutputStream* m_Output;
00322     bool              m_ElementPending;
00323     NPT_Cardinal      m_Depth;
00324     NPT_Cardinal      m_Indentation;
00325     NPT_String        m_IndentationPrefix;
00326     bool              m_ElementHasText;
00327     bool              m_ShrinkEmptyElements;
00328 };
00329 
00330 /*----------------------------------------------------------------------
00331 |   NPT_XmlWriter
00332 +---------------------------------------------------------------------*/
00333 class NPT_XmlWriter
00334 {
00335 public:
00336     // constructor
00337     explicit NPT_XmlWriter(NPT_Cardinal indentation = 0) : m_Indentation(indentation) {}
00338 
00339     // methods
00340     NPT_Result Serialize(NPT_XmlNode& node, NPT_OutputStream& stream);
00341 
00342 private:
00343     // members
00344     NPT_Cardinal m_Indentation;
00345 };
00346 
00347 /*----------------------------------------------------------------------
00348 |   NPT_XmlCanonicalizer
00349 +---------------------------------------------------------------------*/
00350 class NPT_XmlCanonicalizer
00351 {
00352 public:
00353     // methods
00354     NPT_Result Serialize(NPT_XmlNode& node, NPT_OutputStream& stream);
00355 };
00356 
00357 #endif // _NPT_XML_H_