Home | History | Annotate | Download | only in xmllite
      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 TALK_XMLLITE_XMLELEMENT_H_
     29 #define TALK_XMLLITE_XMLELEMENT_H_
     30 
     31 #include <iosfwd>
     32 #include <string>
     33 
     34 #include "talk/base/scoped_ptr.h"
     35 #include "talk/xmllite/qname.h"
     36 
     37 namespace buzz {
     38 
     39 class XmlChild;
     40 class XmlText;
     41 class XmlElement;
     42 class XmlAttr;
     43 
     44 class XmlChild {
     45  public:
     46   XmlChild* NextChild() { return next_child_; }
     47   const XmlChild* NextChild() const { return next_child_; }
     48 
     49   bool IsText() const { return IsTextImpl(); }
     50 
     51   XmlElement* AsElement() { return AsElementImpl(); }
     52   const XmlElement* AsElement() const { return AsElementImpl(); }
     53 
     54   XmlText* AsText() { return AsTextImpl(); }
     55   const XmlText* AsText() const { return AsTextImpl(); }
     56 
     57 
     58  protected:
     59   XmlChild() :
     60     next_child_(NULL) {
     61   }
     62 
     63   virtual bool IsTextImpl() const = 0;
     64   virtual XmlElement* AsElementImpl() const = 0;
     65   virtual XmlText* AsTextImpl() const = 0;
     66 
     67 
     68   virtual ~XmlChild();
     69 
     70  private:
     71   friend class XmlElement;
     72 
     73   XmlChild(const XmlChild& noimpl);
     74 
     75   XmlChild* next_child_;
     76 };
     77 
     78 class XmlText : public XmlChild {
     79  public:
     80   explicit XmlText(const std::string& text) :
     81     XmlChild(),
     82     text_(text) {
     83   }
     84   explicit XmlText(const XmlText& t) :
     85     XmlChild(),
     86     text_(t.text_) {
     87   }
     88   explicit XmlText(const char* cstr, size_t len) :
     89     XmlChild(),
     90     text_(cstr, len) {
     91   }
     92   virtual ~XmlText();
     93 
     94   const std::string& Text() const { return text_; }
     95   void SetText(const std::string& text);
     96   void AddParsedText(const char* buf, int len);
     97   void AddText(const std::string& text);
     98 
     99  protected:
    100   virtual bool IsTextImpl() const;
    101   virtual XmlElement* AsElementImpl() const;
    102   virtual XmlText* AsTextImpl() const;
    103 
    104  private:
    105   std::string text_;
    106 };
    107 
    108 class XmlAttr {
    109  public:
    110   XmlAttr* NextAttr() const { return next_attr_; }
    111   const QName& Name() const { return name_; }
    112   const std::string& Value() const { return value_; }
    113 
    114  private:
    115   friend class XmlElement;
    116 
    117   explicit XmlAttr(const QName& name, const std::string& value) :
    118     next_attr_(NULL),
    119     name_(name),
    120     value_(value) {
    121   }
    122   explicit XmlAttr(const XmlAttr& att) :
    123     next_attr_(NULL),
    124     name_(att.name_),
    125     value_(att.value_) {
    126   }
    127 
    128   XmlAttr* next_attr_;
    129   QName name_;
    130   std::string value_;
    131 };
    132 
    133 class XmlElement : public XmlChild {
    134  public:
    135   explicit XmlElement(const QName& name);
    136   explicit XmlElement(const QName& name, bool useDefaultNs);
    137   explicit XmlElement(const XmlElement& elt);
    138 
    139   virtual ~XmlElement();
    140 
    141   const QName& Name() const { return name_; }
    142   void SetName(const QName& name) { name_ = name; }
    143 
    144   const std::string BodyText() const;
    145   void SetBodyText(const std::string& text);
    146 
    147   const QName FirstElementName() const;
    148 
    149   XmlAttr* FirstAttr();
    150   const XmlAttr* FirstAttr() const
    151     { return const_cast<XmlElement *>(this)->FirstAttr(); }
    152 
    153   // Attr will return an empty string if the attribute isn't there:
    154   // use HasAttr to test presence of an attribute.
    155   const std::string Attr(const StaticQName& name) const;
    156   const std::string Attr(const QName& name) const;
    157   bool HasAttr(const StaticQName& name) const;
    158   bool HasAttr(const QName& name) const;
    159   void SetAttr(const QName& name, const std::string& value);
    160   void ClearAttr(const QName& name);
    161 
    162   XmlChild* FirstChild();
    163   const XmlChild* FirstChild() const {
    164     return const_cast<XmlElement *>(this)->FirstChild();
    165   }
    166 
    167   XmlElement* FirstElement();
    168   const XmlElement* FirstElement() const {
    169     return const_cast<XmlElement *>(this)->FirstElement();
    170   }
    171 
    172   XmlElement* NextElement();
    173   const XmlElement* NextElement() const {
    174     return const_cast<XmlElement *>(this)->NextElement();
    175   }
    176 
    177   XmlElement* FirstWithNamespace(const std::string& ns);
    178   const XmlElement* FirstWithNamespace(const std::string& ns) const {
    179     return const_cast<XmlElement *>(this)->FirstWithNamespace(ns);
    180   }
    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 
    187   XmlElement* FirstNamed(const StaticQName& name);
    188   const XmlElement* FirstNamed(const StaticQName& name) const {
    189     return const_cast<XmlElement *>(this)->FirstNamed(name);
    190   }
    191 
    192   XmlElement* FirstNamed(const QName& name);
    193   const XmlElement* FirstNamed(const QName& name) const {
    194     return const_cast<XmlElement *>(this)->FirstNamed(name);
    195   }
    196 
    197   XmlElement* NextNamed(const StaticQName& name);
    198   const XmlElement* NextNamed(const StaticQName& name) const {
    199     return const_cast<XmlElement *>(this)->NextNamed(name);
    200   }
    201 
    202   XmlElement* NextNamed(const QName& name);
    203   const XmlElement* NextNamed(const QName& name) const {
    204     return const_cast<XmlElement *>(this)->NextNamed(name);
    205   }
    206 
    207   // Finds the first element named 'name'.  If that element can't be found then
    208   // adds one and returns it.
    209   XmlElement* FindOrAddNamedChild(const QName& name);
    210 
    211   const std::string TextNamed(const QName& name) const;
    212 
    213   void InsertChildAfter(XmlChild* predecessor, XmlChild* new_child);
    214   void RemoveChildAfter(XmlChild* predecessor);
    215 
    216   void AddParsedText(const char* buf, int len);
    217   // Note: CDATA is not supported by XMPP, therefore using this function will
    218   // generate non-XMPP compatible XML.
    219   void AddCDATAText(const char* buf, int len);
    220   void AddText(const std::string& text);
    221   void AddText(const std::string& text, int depth);
    222   void AddElement(XmlElement* child);
    223   void AddElement(XmlElement* child, int depth);
    224   void AddAttr(const QName& name, const std::string& value);
    225   void AddAttr(const QName& name, const std::string& value, int depth);
    226   void ClearNamedChildren(const QName& name);
    227   void ClearAttributes();
    228   void ClearChildren();
    229 
    230   static XmlElement* ForStr(const std::string& str);
    231   std::string Str() const;
    232 
    233   bool IsCDATA() const { return cdata_; }
    234 
    235  protected:
    236   virtual bool IsTextImpl() const;
    237   virtual XmlElement* AsElementImpl() const;
    238   virtual XmlText* AsTextImpl() const;
    239 
    240  private:
    241   QName name_;
    242   XmlAttr* first_attr_;
    243   XmlAttr* last_attr_;
    244   XmlChild* first_child_;
    245   XmlChild* last_child_;
    246   bool cdata_;
    247 };
    248 
    249 }  // namespace buzz
    250 
    251 #endif  // TALK_XMLLITE_XMLELEMENT_H_
    252