1 /* 2 * libjingle 3 * Copyright 2004--2005, Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #ifndef _xmlelement_h_ 29 #define _xmlelement_h_ 30 31 #include <iosfwd> 32 #include <string> 33 #include "talk/base/scoped_ptr.h" 34 #include "talk/xmllite/qname.h" 35 36 namespace buzz { 37 38 extern const QName QN_EMPTY; 39 extern const QName QN_XMLNS; 40 41 42 class XmlChild; 43 class XmlText; 44 class XmlElement; 45 class XmlAttr; 46 47 class XmlChild { 48 friend class XmlElement; 49 50 public: 51 52 XmlChild * NextChild() { return pNextChild_; } 53 const XmlChild * NextChild() const { return pNextChild_; } 54 55 bool IsText() const { return IsTextImpl(); } 56 57 XmlElement * AsElement() { return AsElementImpl(); } 58 const XmlElement * AsElement() const { return AsElementImpl(); } 59 60 XmlText * AsText() { return AsTextImpl(); } 61 const XmlText * AsText() const { return AsTextImpl(); } 62 63 64 protected: 65 66 XmlChild() : 67 pNextChild_(NULL) { 68 } 69 70 virtual bool IsTextImpl() const = 0; 71 virtual XmlElement * AsElementImpl() const = 0; 72 virtual XmlText * AsTextImpl() const = 0; 73 74 75 virtual ~XmlChild(); 76 77 private: 78 XmlChild(const XmlChild & noimpl); 79 80 XmlChild * pNextChild_; 81 82 }; 83 84 class XmlText : public XmlChild { 85 public: 86 explicit XmlText(const std::string & text) : 87 XmlChild(), 88 text_(text) { 89 } 90 explicit XmlText(const XmlText & t) : 91 XmlChild(), 92 text_(t.text_) { 93 } 94 explicit XmlText(const char * cstr, size_t len) : 95 XmlChild(), 96 text_(cstr, len) { 97 } 98 virtual ~XmlText(); 99 100 const std::string & Text() const { return text_; } 101 void SetText(const std::string & text); 102 void AddParsedText(const char * buf, int len); 103 void AddText(const std::string & text); 104 105 protected: 106 virtual bool IsTextImpl() const; 107 virtual XmlElement * AsElementImpl() const; 108 virtual XmlText * AsTextImpl() const; 109 110 private: 111 std::string text_; 112 }; 113 114 class XmlAttr { 115 friend class XmlElement; 116 117 public: 118 XmlAttr * NextAttr() const { return pNextAttr_; } 119 const QName & Name() const { return name_; } 120 const std::string & Value() const { return value_; } 121 122 private: 123 explicit XmlAttr(const QName & name, const std::string & value) : 124 pNextAttr_(NULL), 125 name_(name), 126 value_(value) { 127 } 128 explicit XmlAttr(const XmlAttr & att) : 129 pNextAttr_(NULL), 130 name_(att.name_), 131 value_(att.value_) { 132 } 133 134 XmlAttr * pNextAttr_; 135 QName name_; 136 std::string value_; 137 }; 138 139 class XmlElement : public XmlChild { 140 public: 141 explicit XmlElement(const QName & name); 142 explicit XmlElement(const QName & name, bool useDefaultNs); 143 explicit XmlElement(const XmlElement & elt); 144 145 virtual ~XmlElement(); 146 147 const QName& Name() const { return name_; } 148 void SetName(const QName& name) { name_ = name; } 149 150 const std::string & BodyText() const; 151 void SetBodyText(const std::string & text); 152 153 const QName & FirstElementName() const; 154 155 XmlAttr * FirstAttr(); 156 const XmlAttr * FirstAttr() const 157 { return const_cast<XmlElement *>(this)->FirstAttr(); } 158 159 //! Attr will return STR_EMPTY if the attribute isn't there: 160 //! use HasAttr to test presence of an attribute. 161 const std::string & Attr(const QName & name) const; 162 bool HasAttr(const QName & name) const; 163 void SetAttr(const QName & name, const std::string & value); 164 void ClearAttr(const QName & name); 165 166 XmlChild * FirstChild(); 167 const XmlChild * FirstChild() const 168 { return const_cast<XmlElement *>(this)->FirstChild(); } 169 170 XmlElement * FirstElement(); 171 const XmlElement * FirstElement() const 172 { return const_cast<XmlElement *>(this)->FirstElement(); } 173 174 XmlElement * NextElement(); 175 const XmlElement * NextElement() const 176 { return const_cast<XmlElement *>(this)->NextElement(); } 177 178 XmlElement * FirstWithNamespace(const std::string & ns); 179 const XmlElement * FirstWithNamespace(const std::string & ns) const 180 { return const_cast<XmlElement *>(this)->FirstWithNamespace(ns); } 181 182 XmlElement * NextWithNamespace(const std::string & ns); 183 const XmlElement * NextWithNamespace(const std::string & ns) const 184 { return const_cast<XmlElement *>(this)->NextWithNamespace(ns); } 185 186 XmlElement * FirstNamed(const QName & name); 187 const XmlElement * FirstNamed(const QName & name) const 188 { return const_cast<XmlElement *>(this)->FirstNamed(name); } 189 190 XmlElement * NextNamed(const QName & name); 191 const XmlElement * NextNamed(const QName & name) const 192 { return const_cast<XmlElement *>(this)->NextNamed(name); } 193 194 // Finds the first element named 'name'. If that element can't be found then 195 // adds one and returns it. 196 XmlElement* FindOrAddNamedChild(const QName& name); 197 198 const std::string & TextNamed(const QName & name) const; 199 200 void InsertChildAfter(XmlChild * pPredecessor, XmlChild * pNewChild); 201 void RemoveChildAfter(XmlChild * pPredecessor); 202 203 void AddParsedText(const char * buf, int len); 204 // Note: CDATA is not supported by XMPP, therefore using this function will 205 // generate non-XMPP compatible XML. 206 void AddCDATAText(const char * buf, int len); 207 void AddText(const std::string & text); 208 void AddText(const std::string & text, int depth); 209 void AddElement(XmlElement * pelChild); 210 void AddElement(XmlElement * pelChild, int depth); 211 void AddAttr(const QName & name, const std::string & value); 212 void AddAttr(const QName & name, const std::string & value, int depth); 213 void ClearNamedChildren(const QName & name); 214 void ClearAttributes(); 215 void ClearChildren(); 216 217 static XmlElement * ForStr(const std::string & str); 218 std::string Str() const; 219 220 void Print(std::ostream * pout, std::string xmlns[], int xmlnsCount) const; 221 222 bool IsCDATA() const { return cdata_; } 223 224 protected: 225 virtual bool IsTextImpl() const; 226 virtual XmlElement * AsElementImpl() const; 227 virtual XmlText * AsTextImpl() const; 228 229 private: 230 QName name_; 231 XmlAttr * pFirstAttr_; 232 XmlAttr * pLastAttr_; 233 XmlChild * pFirstChild_; 234 XmlChild * pLastChild_; 235 bool cdata_; 236 }; 237 238 } 239 #endif 240