#ifndef _NPT_XML_H_
#define _NPT_XML_H_
#include "NptTypes.h"
#include "NptList.h"
#include "NptStrings.h"
#include "NptStreams.h"
const int NPT_ERROR_XML_INVALID_NESTING = NPT_ERROR_BASE_XML - 0;
const int NPT_ERROR_XML_TAG_MISMATCH = NPT_ERROR_BASE_XML - 1;
const int NPT_ERROR_XML_NO_ROOT = NPT_ERROR_BASE_XML - 2;
const int NPT_ERROR_XML_MULTIPLE_ROOTS = NPT_ERROR_BASE_XML - 3;
#define NPT_XML_ANY_NAMESPACE "*"
#define NPT_XML_NO_NAMESPACE NULL
class NPT_XmlProcessor;
class NPT_XmlAttribute
{
public:
NPT_XmlAttribute(const char* name, const char* value);
NPT_XmlAttribute(const char* prefix, const char* name, const char* value) :
m_Prefix(prefix), m_Name(name), m_Value(value) {}
const NPT_String& GetPrefix() const { return m_Prefix; }
const NPT_String& GetName() const { return m_Name; }
const NPT_String& GetValue() const { return m_Value; }
void SetValue(const char* value) { m_Value = value; }
private:
NPT_String m_Prefix;
NPT_String m_Name;
NPT_String m_Value;
NPT_XmlAttribute(const NPT_XmlAttribute& attribute) :
m_Prefix(attribute.m_Prefix),
m_Name(attribute.m_Name),
m_Value(attribute.m_Value) {}
NPT_XmlAttribute& operator=(const NPT_XmlAttribute& a);
friend class NPT_XmlAttributeFinder;
friend class NPT_XmlAttributeFinderWithPrefix;
};
class NPT_XmlNamespaceMap
{
public:
~NPT_XmlNamespaceMap();
NPT_Result SetNamespaceUri(const char* prefix, const char* uri);
const NPT_String* GetNamespaceUri(const char* prefix);
const NPT_String* GetNamespacePrefix(const char* uri);
private:
class Entry {
public:
Entry(const char* prefix, const char* uri) :
m_Prefix(prefix), m_Uri(uri) {}
NPT_String m_Prefix;
NPT_String m_Uri;
};
NPT_List<Entry*> m_Entries;
friend class NPT_XmlWriter;
friend class NPT_XmlNodeWriter;
friend class NPT_XmlNodeCanonicalWriter;
};
class NPT_XmlElementNode;
class NPT_XmlTextNode;
class NPT_XmlNode
{
public:
typedef enum {
DOCUMENT,
ELEMENT,
TEXT
} Type;
NPT_XmlNode(Type type) : m_Type(type), m_Parent(NULL) {}
virtual ~NPT_XmlNode() {}
Type GetType() const { return m_Type; }
NPT_XmlNode* GetParent() const { return m_Parent; }
virtual NPT_XmlElementNode* AsElementNode() { return NULL; }
virtual const NPT_XmlElementNode* AsElementNode() const { return NULL; }
virtual NPT_XmlTextNode* AsTextNode() { return NULL; }
virtual const NPT_XmlTextNode* AsTextNode() const { return NULL; }
protected:
virtual void SetParent(NPT_XmlNode* parent) { m_Parent = parent; }
Type m_Type;
NPT_XmlNode* m_Parent;
friend class NPT_XmlNodeFinder;
friend class NPT_XmlSerializer;
friend class NPT_XmlWriter;
friend class NPT_XmlElementNode;
};
class NPT_XmlElementNode : public NPT_XmlNode
{
public:
NPT_XmlElementNode(const char* tag);
NPT_XmlElementNode(const char* prefix, const char* tag);
virtual ~NPT_XmlElementNode();
NPT_List<NPT_XmlNode*>& GetChildren() { return m_Children; }
const NPT_List<NPT_XmlNode*>&
GetChildren() const { return m_Children; }
NPT_XmlElementNode* GetChild(const char* tag,
const char* namespc = NPT_XML_NO_NAMESPACE,
NPT_Ordinal n=0) const;
NPT_Result AddChild(NPT_XmlNode* child);
NPT_Result SetAttribute(const char* prefix,
const char* name,
const char* value);
NPT_Result SetAttribute(const char* name,
const char* value);
NPT_Result AddText(const char* text);
NPT_List<NPT_XmlAttribute*>&
GetAttributes() { return m_Attributes; }
const NPT_List<NPT_XmlAttribute*>&
GetAttributes() const { return m_Attributes; }
const NPT_String* GetAttribute(const char* name,
const char* namespc = NPT_XML_NO_NAMESPACE) const;
const NPT_String& GetPrefix() const { return m_Prefix; }
const NPT_String& GetTag() const { return m_Tag; }
const NPT_String* GetText(NPT_Ordinal n=0) const;
NPT_Result MakeStandalone();
const NPT_String* GetNamespace() const;
NPT_Result SetNamespaceUri(const char* prefix, const char* uri);
const NPT_String* GetNamespaceUri(const char* prefix) const;
const NPT_String* GetNamespacePrefix(const char* uri) const;
NPT_XmlElementNode* AsElementNode() { return this; }
const NPT_XmlElementNode* AsElementNode() const { return this; }
protected:
void SetParent(NPT_XmlNode* parent);
void SetNamespaceParent(NPT_XmlElementNode* parent);
void RelinkNamespaceMaps();
NPT_Result AddAttribute(const char* name, const char* value);
NPT_String m_Prefix;
NPT_String m_Tag;
NPT_List<NPT_XmlNode*> m_Children;
NPT_List<NPT_XmlAttribute*> m_Attributes;
NPT_XmlNamespaceMap* m_NamespaceMap;
NPT_XmlElementNode* m_NamespaceParent;
friend class NPT_XmlTagFinder;
friend class NPT_XmlSerializer;
friend class NPT_XmlWriter;
friend class NPT_XmlNodeWriter;
friend class NPT_XmlNodeCanonicalWriter;
friend class NPT_XmlParser;
friend class NPT_XmlProcessor;
friend class NPT_XmlNamespaceCollapser;
};
class NPT_XmlTextNode : public NPT_XmlNode
{
public:
typedef enum {
CHARACTER_DATA,
IGNORABLE_WHITESPACE,
CDATA_SECTION,
ENTITY_REFERENCE,
COMMENT
} TokenType;
NPT_XmlTextNode(TokenType token_type, const char* text);
const NPT_String& GetString() const { return m_Text; }
NPT_XmlTextNode* AsTextNode() { return this; }
const NPT_XmlTextNode* AsTextNode() const { return this; }
private:
NPT_String m_Text;
};
class NPT_XmlParser
{
public:
NPT_XmlParser(bool keep_whitespace = true);
virtual ~NPT_XmlParser();
virtual NPT_Result Parse(const char* xml,
NPT_XmlNode*& tree,
bool incremental=false);
virtual NPT_Result Parse(const char* xml,
NPT_Size size,
NPT_XmlNode*& tree,
bool incremental=false);
virtual NPT_Result Parse(NPT_InputStream& stream,
NPT_XmlNode*& tree,
bool incremental=false);
virtual NPT_Result Parse(NPT_InputStream& stream,
NPT_Size& size,
NPT_XmlNode*& tree,
bool incremental=false);
protected:
NPT_Result OnStartElement(const char* name);
NPT_Result OnElementAttribute(const char* name, const char* value);
NPT_Result OnEndElement(const char* name);
NPT_Result OnCharacterData(const char* data, unsigned long size);
void RemoveIgnorableWhitespace();
NPT_XmlProcessor* m_Processor;
NPT_XmlElementNode* m_Root;
NPT_XmlElementNode* m_CurrentElement;
bool m_KeepWhitespace;
private:
void Reset();
friend class NPT_XmlProcessor;
};
class NPT_XmlSerializer
{
public:
NPT_XmlSerializer(NPT_OutputStream* output,
NPT_Cardinal indentation = 0,
bool shrink_empty_elements = true,
bool add_xml_decl = false);
virtual ~NPT_XmlSerializer();
virtual NPT_Result StartDocument();
virtual NPT_Result EndDocument();
virtual NPT_Result StartElement(const char* prefix, const char* name);
virtual NPT_Result EndElement(const char* prefix, const char* name);
virtual NPT_Result Attribute(const char* prefix, const char* name, const char* value);
virtual NPT_Result Text(const char* text);
virtual NPT_Result CdataSection(const char* data);
virtual NPT_Result Comment(const char* comment);
protected:
void EscapeChar(unsigned char c, char* text);
NPT_Result ProcessPending();
NPT_Result OutputEscapedString(const char* text, bool attribute);
void OutputIndentation(bool start);
NPT_OutputStream* m_Output;
bool m_ElementPending;
NPT_Cardinal m_Depth;
NPT_Cardinal m_Indentation;
NPT_String m_IndentationPrefix;
bool m_ElementHasText;
bool m_ShrinkEmptyElements;
bool m_AddXmlDecl;
};
class NPT_XmlWriter
{
public:
explicit NPT_XmlWriter(NPT_Cardinal indentation = 0) : m_Indentation(indentation) {}
NPT_Result Serialize(NPT_XmlNode& node,
NPT_OutputStream& stream,
bool add_xml_decl = false);
private:
NPT_Cardinal m_Indentation;
};
class NPT_XmlCanonicalizer
{
public:
NPT_Result Serialize(NPT_XmlNode& node,
NPT_OutputStream& stream,
bool add_xml_decl = false);
};
#endif