gloox 1.0
tag.h
00001 /*
00002   Copyright (c) 2005-2009 by Jakob Schroeter <js@camaya.net>
00003   This file is part of the gloox library. http://camaya.net/gloox
00004 
00005   This software is distributed under a license. The full license
00006   agreement can be found in the file LICENSE in this distribution.
00007   This software may not be copied, modified, sold or distributed
00008   other than expressed in the named license agreement.
00009 
00010   This software is distributed without any warranty.
00011 */
00012 
00013 
00014 #ifndef TAG_H__
00015 #define TAG_H__
00016 
00017 #include "gloox.h"
00018 
00019 #include <string>
00020 #include <list>
00021 #include <utility>
00022 
00023 namespace gloox
00024 {
00025 
00026   class Tag;
00027 
00031   typedef std::list<Tag*> TagList;
00032 
00036   typedef std::list<const Tag*> ConstTagList;
00037 
00046   class GLOOX_API Tag
00047   {
00048 
00049     friend class Parser;
00050 
00051     public:
00052 
00059       class GLOOX_API Attribute
00060       {
00061 
00062         friend class Tag;
00063 
00064         public:
00077           Attribute( Tag* parent, const std::string& name, const std::string& value,
00078                      const std::string& xmlns = EmptyString );
00079 
00086           Attribute( const std::string& name, const std::string& value,
00087                      const std::string& xmlns = EmptyString );
00088 
00093           Attribute( const Attribute& attr );
00094 
00098           virtual ~Attribute() {}
00099 
00104           const std::string& name() const { return m_name; }
00105 
00110           const std::string& value() const { return m_value; }
00111 
00118           bool setValue( const std::string& value );
00119 
00124           const std::string& xmlns() const;
00125 
00132           bool setXmlns( const std::string& xmlns );
00133 
00140           bool setPrefix( const std::string& prefix );
00141 
00146           const std::string& prefix() const;
00147 
00152           const std::string xml() const;
00153 
00158           bool operator==( const Attribute &right ) const
00159             { return m_name == right.m_name && m_value == right.m_value && m_xmlns == right.m_xmlns; }
00160 
00165           bool operator!=( const Attribute &right ) const
00166             { return !( *this == right ); }
00167 
00171           operator bool() const { return !m_name.empty(); }
00172 
00173         private:
00174           void init( const std::string& name, const std::string& value,
00175                      const std::string& xmlns );
00176           Tag* m_parent;
00177           std::string m_name;
00178           std::string m_value;
00179           std::string m_xmlns;
00180           std::string m_prefix;
00181 
00182       };
00183 
00187       typedef std::list<Attribute*> AttributeList;
00188 
00194       Tag( const std::string& name, const std::string& cdata = EmptyString );
00195 
00203       Tag( Tag* parent, const std::string& name, const std::string& cdata = EmptyString );
00204 
00211       Tag( const std::string& name, const std::string& attrib, const std::string& value );
00212 
00221       Tag( Tag* parent, const std::string& name, const std::string& attrib, const std::string& value );
00222 
00226       virtual ~Tag();
00227 
00233       const std::string xml() const;
00234 
00242       bool setPrefix( const std::string& prefix );
00243 
00249       const std::string& prefix() const { return m_prefix; }
00250 
00256       const std::string& prefix( const std::string& xmlns ) const;
00257 
00258       /* *
00259        * Adds an XML namespace declaration to the Tag. If @b def is false, a unique prefix will
00260        * be created, else the default namespace is set (no prefix).
00261        * @param xmlns The namespace value.
00262        * @param def If @b true, this sets the default namespace; if @b false, a unique namespace
00263        * prefix will be created (unless one already exists for the namespace) and used for
00264        * all subsequent references to the same namespace.
00265        * @since 1.0
00266        */
00267 //       const std::string addXmlns( const std::string& xmlns, bool def );
00268 
00278       bool setXmlns( const std::string& xmlns, const std::string& prefix = EmptyString );
00279 
00286       const std::string& xmlns() const;
00287 
00305       const std::string& xmlns( const std::string& prefix ) const;
00306 
00317       bool addAttribute( Attribute* attr );
00318 
00327       bool addAttribute( const std::string& name, const std::string& value );
00328 
00338       bool addAttribute( const std::string& name, int value );
00339 
00349       bool addAttribute( const std::string& name, long value );
00350 
00359       void setAttributes( const AttributeList& attributes );
00360 
00365       void addChild( Tag* child );
00366 
00372       void addChildCopy( const Tag* child );
00373 
00380       bool setCData( const std::string& cdata );
00381 
00388       bool addCData( const std::string& cdata );
00389 
00394       const std::string& name() const { return m_name; }
00395 
00400       const std::string cdata() const;
00401 
00406       const AttributeList& attributes() const;
00407 
00412       const TagList& children() const;
00413 
00419       const std::string& findAttribute( const std::string& name ) const;
00420 
00427       bool hasAttribute( const std::string& name, const std::string& value = EmptyString ) const;
00428 
00435       Tag* findChild( const std::string& name ) const;
00436 
00445       Tag* findChild( const std::string& name, const std::string& attr,
00446                       const std::string& value = EmptyString ) const;
00447 
00456       bool hasChild( const std::string& name, const std::string& attr = EmptyString,
00457                      const std::string& value = EmptyString ) const;
00458 
00466       Tag* findChildWithAttrib( const std::string& attr, const std::string& value = EmptyString ) const;
00467 
00475       inline bool hasChildWithAttrib( const std::string& attr,
00476                                       const std::string& value = EmptyString ) const
00477         { return findChildWithAttrib( attr, value ) ? true : false; }
00478 
00487       TagList findChildren( const std::string& name, const std::string& xmlns = EmptyString ) const;
00488 
00495       void removeChild( const std::string& name, const std::string& xmlns = EmptyString );
00496 
00502       void removeChild( Tag* tag );
00503 
00510       void removeAttribute( const std::string& attr, const std::string& value = EmptyString,
00511                             const std::string& xmlns = EmptyString );
00512 
00520       bool hasChildWithCData( const std::string& name, const std::string& cdata ) const;
00521 
00526       Tag* parent() const { return m_parent; }
00527 
00533       Tag* clone() const;
00534 
00545       const std::string findCData( const std::string& expression ) const;
00546 
00557       const Tag* findTag( const std::string& expression ) const;
00558 
00568       ConstTagList findTagList( const std::string& expression ) const;
00569 
00575       bool operator==( const Tag &right ) const;
00576 
00582       bool operator!=( const Tag &right ) const { return !( *this == right ); }
00583 
00587       operator bool() const { return !m_name.empty(); }
00588 
00589     private:
00595       Tag( Tag* tag );
00596 
00600       enum XPathError
00601       {
00602         XPNoError,                  
00603         XPExpectedLeftOperand,      
00604         XPUnexpectedToken
00605       };
00606 
00607       enum NodeType
00608       {
00609         TypeTag,                    
00610         TypeString                  
00611       };
00612 
00613       struct Node
00614       {
00615         Node( NodeType _type, Tag* _tag ) : type( _type ), tag( _tag ) {}
00616         Node( NodeType _type, std::string* _str ) : type( _type ), str( _str ) {}
00617         ~Node() {}
00618 
00619         NodeType type;
00620         union
00621         {
00622           Tag* tag;
00623           std::string* str;
00624         };
00625       };
00626 
00627       typedef std::list<Node*> NodeList;
00628 
00629       Tag* m_parent;
00630       TagList* m_children;
00631       StringPList* m_cdata;
00632       AttributeList* m_attribs;
00633       NodeList* m_nodes;
00634       std::string m_name;
00635       std::string m_xmlns;
00636       StringMap* m_xmlnss;
00637       std::string m_prefix;
00638 
00639       enum TokenType
00640       {
00641         XTNone,
00642         XTLeftParenthesis,
00643         XTRightParenthesis,
00644         XTNodeSet,
00645         XTInteger,
00646         XTElement,
00647         XTLeftBracket,
00648         XTRightBracket,
00649         XTFunction,
00650         XTAsterisk,
00651         XTAttribute,
00652         XTLiteralInside,
00653         XTLiteral,
00654         XTDot,
00655         XTDoubleDot,
00656         XTOperatorOr,
00657         XTOperatorAnd,
00658         XTOperatorEq,
00659         XTOperatorNe,
00660         XTOperatorGt,
00661         XTOperatorLt,
00662         XTOperatorLtEq,
00663         XTOperatorGtEq,
00664         XTOperatorPlus,
00665         XTOperatorMinus,
00666         XTOperatorMul,
00667         XTOperatorDiv,
00668         XTOperatorMod,
00669         XTUnion,
00670         XTSlash,
00671         XTDoubleSlash
00672       };
00673 
00679       void setXmlns( StringMap* xmlns )
00680         { delete m_xmlnss; m_xmlnss = xmlns; }
00681 
00682       Tag* parse( const std::string& expression, unsigned& len, TokenType border = XTNone ) const;
00683 
00684       void closePreviousToken( Tag**, Tag**, TokenType&, std::string& ) const;
00685       void addToken( Tag **root, Tag **current, TokenType type, const std::string& token ) const;
00686       void addOperator( Tag **root, Tag **current, Tag* arg, TokenType type,
00687                         const std::string& token ) const;
00688       bool addPredicate( Tag **root, Tag **current, Tag* token ) const;
00689 
00690       TagList findChildren( const TagList& list, const std::string& name,
00691                             const std::string& xmlns = EmptyString ) const;
00692       ConstTagList evaluateTagList( Tag* token ) const;
00693       ConstTagList evaluateUnion( Tag* token ) const;
00694       ConstTagList allDescendants() const;
00695 
00696       static TokenType getType( const std::string& c );
00697 
00698       static bool isWhitespace( const char c );
00699       bool isNumber() const;
00700 
00701       bool evaluateBoolean( Tag* token ) const;
00702       bool evaluatePredicate( Tag* token ) const { return evaluateBoolean( token ); }
00703       bool evaluateEquals( Tag* token ) const;
00704 
00705       static void add( ConstTagList& one, const ConstTagList& two );
00706   };
00707 
00708 }
00709 
00710 #endif // TAG_H__