1/*
2 *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11#ifndef WEBRTC_LIBJINGLE_XMLLITE_XMLELEMENT_H_
12#define WEBRTC_LIBJINGLE_XMLLITE_XMLELEMENT_H_
13
14#include <iosfwd>
15#include <string>
16
17#include "webrtc/libjingle/xmllite/qname.h"
18#include "webrtc/base/scoped_ptr.h"
19
20namespace buzz {
21
22class XmlChild;
23class XmlText;
24class XmlElement;
25class XmlAttr;
26
27class XmlChild {
28 public:
29  XmlChild* NextChild() { return next_child_; }
30  const XmlChild* NextChild() const { return next_child_; }
31
32  bool IsText() const { return IsTextImpl(); }
33
34  XmlElement* AsElement() { return AsElementImpl(); }
35  const XmlElement* AsElement() const { return AsElementImpl(); }
36
37  XmlText* AsText() { return AsTextImpl(); }
38  const XmlText* AsText() const { return AsTextImpl(); }
39
40
41 protected:
42  XmlChild() :
43    next_child_(NULL) {
44  }
45
46  virtual bool IsTextImpl() const = 0;
47  virtual XmlElement* AsElementImpl() const = 0;
48  virtual XmlText* AsTextImpl() const = 0;
49
50
51  virtual ~XmlChild();
52
53 private:
54  friend class XmlElement;
55
56  XmlChild(const XmlChild& noimpl);
57
58  XmlChild* next_child_;
59};
60
61class XmlText : public XmlChild {
62 public:
63  explicit XmlText(const std::string& text) :
64    XmlChild(),
65    text_(text) {
66  }
67  explicit XmlText(const XmlText& t) :
68    XmlChild(),
69    text_(t.text_) {
70  }
71  explicit XmlText(const char* cstr, size_t len) :
72    XmlChild(),
73    text_(cstr, len) {
74  }
75  virtual ~XmlText();
76
77  const std::string& Text() const { return text_; }
78  void SetText(const std::string& text);
79  void AddParsedText(const char* buf, int len);
80  void AddText(const std::string& text);
81
82 protected:
83  virtual bool IsTextImpl() const;
84  virtual XmlElement* AsElementImpl() const;
85  virtual XmlText* AsTextImpl() const;
86
87 private:
88  std::string text_;
89};
90
91class XmlAttr {
92 public:
93  XmlAttr* NextAttr() const { return next_attr_; }
94  const QName& Name() const { return name_; }
95  const std::string& Value() const { return value_; }
96
97 private:
98  friend class XmlElement;
99
100  explicit XmlAttr(const QName& name, const std::string& value) :
101    next_attr_(NULL),
102    name_(name),
103    value_(value) {
104  }
105  explicit XmlAttr(const XmlAttr& att) :
106    next_attr_(NULL),
107    name_(att.name_),
108    value_(att.value_) {
109  }
110
111  XmlAttr* next_attr_;
112  QName name_;
113  std::string value_;
114};
115
116class XmlElement : public XmlChild {
117 public:
118  explicit XmlElement(const QName& name);
119  explicit XmlElement(const QName& name, bool useDefaultNs);
120  explicit XmlElement(const XmlElement& elt);
121
122  virtual ~XmlElement();
123
124  const QName& Name() const { return name_; }
125  void SetName(const QName& name) { name_ = name; }
126
127  const std::string BodyText() const;
128  void SetBodyText(const std::string& text);
129
130  const QName FirstElementName() const;
131
132  XmlAttr* FirstAttr();
133  const XmlAttr* FirstAttr() const
134    { return const_cast<XmlElement *>(this)->FirstAttr(); }
135
136  // Attr will return an empty string if the attribute isn't there:
137  // use HasAttr to test presence of an attribute.
138  const std::string Attr(const StaticQName& name) const;
139  const std::string Attr(const QName& name) const;
140  bool HasAttr(const StaticQName& name) const;
141  bool HasAttr(const QName& name) const;
142  void SetAttr(const QName& name, const std::string& value);
143  void ClearAttr(const QName& name);
144
145  XmlChild* FirstChild();
146  const XmlChild* FirstChild() const {
147    return const_cast<XmlElement *>(this)->FirstChild();
148  }
149
150  XmlElement* FirstElement();
151  const XmlElement* FirstElement() const {
152    return const_cast<XmlElement *>(this)->FirstElement();
153  }
154
155  XmlElement* NextElement();
156  const XmlElement* NextElement() const {
157    return const_cast<XmlElement *>(this)->NextElement();
158  }
159
160  XmlElement* FirstWithNamespace(const std::string& ns);
161  const XmlElement* FirstWithNamespace(const std::string& ns) const {
162    return const_cast<XmlElement *>(this)->FirstWithNamespace(ns);
163  }
164
165  XmlElement* NextWithNamespace(const std::string& ns);
166  const XmlElement* NextWithNamespace(const std::string& ns) const {
167    return const_cast<XmlElement *>(this)->NextWithNamespace(ns);
168  }
169
170  XmlElement* FirstNamed(const StaticQName& name);
171  const XmlElement* FirstNamed(const StaticQName& name) const {
172    return const_cast<XmlElement *>(this)->FirstNamed(name);
173  }
174
175  XmlElement* FirstNamed(const QName& name);
176  const XmlElement* FirstNamed(const QName& name) const {
177    return const_cast<XmlElement *>(this)->FirstNamed(name);
178  }
179
180  XmlElement* NextNamed(const StaticQName& name);
181  const XmlElement* NextNamed(const StaticQName& name) const {
182    return const_cast<XmlElement *>(this)->NextNamed(name);
183  }
184
185  XmlElement* NextNamed(const QName& name);
186  const XmlElement* NextNamed(const QName& name) const {
187    return const_cast<XmlElement *>(this)->NextNamed(name);
188  }
189
190  // Finds the first element named 'name'.  If that element can't be found then
191  // adds one and returns it.
192  XmlElement* FindOrAddNamedChild(const QName& name);
193
194  const std::string TextNamed(const QName& name) const;
195
196  void InsertChildAfter(XmlChild* predecessor, XmlChild* new_child);
197  void RemoveChildAfter(XmlChild* predecessor);
198
199  void AddParsedText(const char* buf, int len);
200  // Note: CDATA is not supported by XMPP, therefore using this function will
201  // generate non-XMPP compatible XML.
202  void AddCDATAText(const char* buf, int len);
203  void AddText(const std::string& text);
204  void AddText(const std::string& text, int depth);
205  void AddElement(XmlElement* child);
206  void AddElement(XmlElement* child, int depth);
207  void AddAttr(const QName& name, const std::string& value);
208  void AddAttr(const QName& name, const std::string& value, int depth);
209  void ClearNamedChildren(const QName& name);
210  void ClearAttributes();
211  void ClearChildren();
212
213  static XmlElement* ForStr(const std::string& str);
214  std::string Str() const;
215
216  bool IsCDATA() const { return cdata_; }
217
218 protected:
219  virtual bool IsTextImpl() const;
220  virtual XmlElement* AsElementImpl() const;
221  virtual XmlText* AsTextImpl() const;
222
223 private:
224  QName name_;
225  XmlAttr* first_attr_;
226  XmlAttr* last_attr_;
227  XmlChild* first_child_;
228  XmlChild* last_child_;
229  bool cdata_;
230};
231
232}  // namespace buzz
233
234#endif  // WEBRTC_LIBJINGLE_XMLLITE_XMLELEMENT_H_
235