xmpp_stanza.hpp 3.44 KB
Newer Older
1 2 3 4 5 6 7
#ifndef XMPP_STANZA_INCLUDED
# define XMPP_STANZA_INCLUDED

#include <unordered_map>
#include <string>
#include <vector>

louiz’'s avatar
louiz’ committed
8
std::string xml_escape(const std::string& data);
9
std::string xml_unescape(const std::string& data);
louiz’'s avatar
louiz’ committed
10

11 12 13 14 15 16
/**
 * Represent an XML node. It has
 * - A parent XML node (in the case of the first-level nodes, the parent is
     nullptr)
 * - zero, one or more children XML nodes
 * - A name
17 18 19
 * - A map of attributes
 * - inner data (text inside the node)
 * - tail data (text just after the node)
20 21 22 23 24 25 26 27
 */
class XmlNode
{
public:
  explicit XmlNode(const std::string& name, XmlNode* parent);
  explicit XmlNode(const std::string& name);
  XmlNode(XmlNode&& node):
    name(std::move(node.name)),
28 29
    parent(node.parent),
    closed(node.closed),
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
    attributes(std::move(node.attributes)),
    children(std::move(node.children)),
    inner(std::move(node.inner)),
    tail(std::move(node.tail))
  {
    node.parent = nullptr;
  }

  ~XmlNode();

  void delete_all_children();
  void set_attribute(const std::string& name, const std::string& value);
  /**
   * Set the content of the tail, that is the text just after this node
   */
  void set_tail(const std::string& data);
  /**
47 48 49 50 51 52 53
   * Append the given data to the content of the tail. This exists because
   * the expat library may provide the complete text of an element in more
   * than one call
   */
  void add_to_tail(const std::string& data);
  /**
   * Set the content of the inner, that is the text inside this node.
54 55
   */
  void set_inner(const std::string& data);
56 57 58 59 60
  /**
   * Append the given data to the content of the inner. For the reason
   * described in add_to_tail comment.
   */
  void add_to_inner(const std::string& data);
louiz’'s avatar
louiz’ committed
61 62 63 64
  /**
   * Get the content of inner
   */
  std::string get_inner() const;
65 66 67 68
  /**
   * Get the content of the tail
   */
  std::string get_tail() const;
louiz’'s avatar
louiz’ committed
69 70 71 72
  /**
   * Get a pointer to the first child element with that name
   */
  XmlNode* get_child(const std::string& name) const;
73 74 75 76 77 78 79 80 81
  /**
   * Add a node child to this node. Assign this node to the child’s parent.
   * Returns a pointer to the newly added child.
   */
  XmlNode* add_child(XmlNode* child);
  XmlNode* add_child(XmlNode&& child);
  /**
   * Returns the last of the children
   */
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
  XmlNode* get_last_child() const;
  /**
   * Mark this node as closed, nothing else
   */
  void close();
  XmlNode* get_parent() const;
  const std::string& get_name() const;
  /**
   * Serialize the stanza into a string
   */
  std::string to_string() const;
  /**
   * Whether or not this node has at least one child (if not, this is a leaf
   * node)
   */
  bool has_children() const;
  /**
99
   * Gets the value for the given attribute, returns an empty string if the
100 101
   * node as no such attribute.
   */
102
  const std::string get_tag(const std::string& name) const;
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
  /**
   * Use this to set an attribute's value, like node["id"] = "12";
   */
  std::string& operator[](const std::string& name);

private:
  std::string name;
  XmlNode* parent;
  bool closed;
  std::unordered_map<std::string, std::string> attributes;
  std::vector<XmlNode*> children;
  std::string inner;
  std::string tail;

  XmlNode(const XmlNode&) = delete;
  XmlNode& operator=(const XmlNode&) = delete;
  XmlNode& operator=(XmlNode&&) = delete;
};

/**
 * An XMPP stanza is just an XML node of level 2 in the XMPP document (the
 * level 1 ones are the <stream::stream/>, and the ones about 2 are just the
 * content of the stanzas)
 */
typedef XmlNode Stanza;

#endif // XMPP_STANZA_INCLUDED