ximol/xml/attributes.hpp

Go to the documentation of this file.
00001 /*****************************************************************************\
00002  *                                                                           *
00003  * library XiMoL                                                             *
00004  * Copyright (C) 2002, 2003, 2004 Florent Tournois                           *
00005  *                                                                           *
00006  * This library is free software; you can redistribute it and/or             *
00007  * modify it under the terms of the GNU Lesser General Public                *
00008  * License as published by the Free Software Foundation; either              *
00009  * version 2.1 of the License, or (at your option) any later version.        *
00010  *                                                                           *
00011  * This library is distributed in the hope that it will be useful,           *
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
00014  * Lesser General Public License for more details.                           *
00015  *                                                                           *
00016  * You should have received a copy of the GNU Lesser General Public          *
00017  * License along with this library; if not, write to the Free Software       *
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA   *
00019  *                                                                           *
00020 \*****************************************************************************/
00021 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00022 /** \file 
00023         \brief attributes declaration.
00024         
00025         \author Tournois Florent
00026         \version 1.0
00027 
00028     $Id: attributes.hpp,v 1.20 2004/02/25 18:59:13 tournois Exp $
00029     $Log: attributes.hpp,v $
00030     Revision 1.20  2004/02/25 18:59:13  tournois
00031     imporve the gcc compatibility.
00032 
00033     Revision 1.19  2004/02/22 22:36:24  hfp
00034     *** empty log message ***
00035 
00036     Revision 1.18  2004/02/22 10:27:34  tournois
00037     Add some doc.
00038 
00039     Revision 1.17  2004/02/22 09:54:21  tournois
00040     Change years on the copyright.
00041 
00042     Revision 1.16  2004/02/19 18:59:28  tournois
00043     attribute doc
00044 
00045     Revision 1.15  2004/01/29 20:52:35  tournois
00046     doc and tutorial.
00047 
00048     Revision 1.14  2004/01/18 11:40:58  tournois
00049     Add the pattern facet.
00050 
00051     Revision 1.13  2003/12/10 20:45:51  tournois
00052     no message
00053 
00054     Revision 1.12  2003/12/09 19:57:28  tournois
00055     Fix some bugs about attributes classes.
00056 
00057     Revision 1.11  2003/12/05 13:04:41  hfp
00058     adapt supplied functions
00059 
00060     Revision 1.10  2003/12/04 14:44:10  hfp
00061     shortcut/uri-mapping includes default namespace
00062     ns_map swaps key with value -> faster find for main use-case
00063     throwing error in some cases
00064     interface is based on map (insert, fiind)
00065     mis-use of special values on return removed (find etc.)
00066     size() returns an size_t (unsigned)
00067 
00068     Revision 1.9  2003/12/03 12:28:46  hfp
00069     swap, copy construction and assignment
00070 
00071     Revision 1.8  2003/11/19 20:52:54  tournois
00072     Add new manipulator for stag and etag.
00073     Correct bugs and add tests.
00074 
00075     Revision 1.7  2003/11/18 18:54:52  tournois
00076     Add str_cast and drop the transformation.hpp file.
00077 
00078     Revision 1.6  2003/11/15 22:52:57  tournois
00079     Add somes function arround attributes and tests for attributes.
00080 
00081     Revision 1.5  2003/11/14 13:30:20  tournois
00082     change the attributes class and fix some bugs.
00083 
00084     Revision 1.4  2003/11/02 19:23:01  tournois
00085     Go to the boost coding standard.
00086     Change all name to lower case.
00087 
00088     Revision 1.3  2003/10/25 13:53:40  hfp
00089     review and separation
00090 
00091     Revision 1.2  2003/09/28 16:46:13  hfp
00092     The "uri" default argument of the add()-method has changed the construction of default-value (::str::string() -> xstring()), because of non-existing conversion path from string to xstring.
00093 
00094     Revision 1.1  2003/09/24 08:28:18  tournois
00095     Create the namespace Encoders, Parser, Xml
00096     Change the library organization.
00097     add VC7.1 project for this organization.
00098 
00099   */
00100 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00101 #ifndef XIMOL_ATTRIBUTES_HPP_
00102 #define XIMOL_ATTRIBUTES_HPP_
00103 
00104 #include <ximol/stop_warnings.hpp>
00105 #include <ximol/export_defs.hpp>
00106 #include <ximol/str_cast.hpp>
00107 #include <ximol/typedefs.hpp>
00108 
00109 #include <map>
00110 
00111 
00112 // forwarded declarations
00113 XIMOL_BEGIN_NAMESPACE
00114         class xistream;
00115         class xostream;
00116         class xistringstream;
00117         class xostringstream;
00118 XIMOL_END_NAMESPACE
00119 
00120 
00121 XIMOL_XML_BEGIN_NAMESPACE
00122 
00123 //=============================================================================
00124 /** A simple class to contain attributes of a tag.
00125   * @ingroup xml
00126   * This class can read and write attributes for an XML tag.
00127   * This class contain :
00128   *      - a map ((uri,name),value)
00129   *      - a map (uri, short_cut)
00130   *
00131   *  the short_cut for the default uri is an empty string.
00132   */ 
00133 //=============================================================================
00134 class XIMOL_EXPORT attributes {
00135 public: // nested types
00136         typedef xstring attribute_type; // should be a variant
00137 
00138 private: // nested types
00139         typedef struct XIMOL_EXPORT ::std::pair<xstring, xstring> qname_type;
00140 
00141     typedef class XIMOL_EXPORT ::std::map<qname_type, attribute_type> map_type;
00142 
00143         typedef class XIMOL_EXPORT ::std::map<
00144                 xstring,        // the short cut type
00145                 xstring         // the uri type
00146         > map_uri_type;
00147 
00148 public: // nested types
00149         typedef map_type::const_iterator const_iterator;
00150     typedef map_type::iterator iterator;
00151 
00152     typedef map_uri_type::const_iterator const_ns_iterator;
00153     typedef map_uri_type::iterator ns_iterator;
00154 
00155 private: // class attributes
00156         static xstring const shortcut_default_uri_;
00157 
00158 public: // constructor(s) & destructor
00159     attributes();
00160 
00161     attributes(attributes const& rhs);
00162 
00163     ~attributes();
00164 
00165 public: // methods
00166         /**
00167          * Exchange the contents of this object and
00168          * the right-hand-side one.
00169          * This is also a root of exception safety.
00170          */
00171         void swap(attributes& rhs) throw();
00172 
00173         /**
00174          * Assignment operator based on swap.
00175          */
00176         attributes& operator=(attributes const& rhs) {
00177                 attributes temp(rhs);
00178                 swap(temp);
00179                 return *this;
00180         }
00181 
00182 
00183         /// delete all members.
00184         void clear();
00185 
00186 
00187         /// number of attributes
00188         size_t size() const                                             { return map_.size(); }
00189 
00190 
00191         ///@name iterator
00192         //@{
00193         iterator begin()                                                { return map_.begin(); }
00194         const_iterator  begin() const                   { return map_.begin(); }
00195 
00196         iterator end()                                                  { return map_.end(); }
00197         const_iterator end() const                              { return map_.end(); }
00198 
00199 
00200         ns_iterator ns_begin()                                  { return map_uri_.begin(); }
00201         const_ns_iterator ns_begin() const              { return map_uri_.begin(); }
00202 
00203         ns_iterator ns_end()                                    { return map_uri_.end(); }
00204         const_ns_iterator ns_end() const                { return map_uri_.end(); }
00205         //@}
00206 
00207 
00208         /** add attributes.
00209           * This function add all the attributes and namespace.
00210       * All value of the argument will replace the value of the cuurent object.
00211       */
00212         attributes& operator+=(attributes const& rhs);
00213 
00214 
00215         /// Find a namespace (uri) for a given short cut.
00216         const_ns_iterator find_namespace(xstring const& short_ns) const;
00217 
00218         /// Find a short cut for a full namespace (uri).
00219         const_ns_iterator find_short_namespace(xstring const& uri) const;
00220 
00221 
00222         /// Insert a namespace mapping.
00223         std::pair<ns_iterator, bool> // return type
00224         insert_namespace(xstring const& short_ns, xstring const& uri);
00225 
00226 
00227         /// Find the default namespace.
00228         const_ns_iterator find_namespace() const        { return find_namespace(shortcut_default_uri_); }
00229 
00230         /// Set the default namespace.
00231         void set_namespace(xstring const& uri)          { insert_namespace(shortcut_default_uri_, uri); }
00232 
00233         
00234         /** Insert an attribute.
00235      *  If the attribute does not exist, it set the value
00236      */
00237         std::pair<iterator, bool> // return type
00238         insert(
00239                 /** Can be the uri or a short cut */
00240                 xstring const& namespace_name,
00241                 /** The name of the attribute */
00242                 xstring const& name,
00243                 /** To be completed: Should be a variant. */
00244                 xstring const& value);
00245 
00246         /// Set an attribute.
00247         void // return type
00248         set(
00249                 /** Can be the uri or a short cut */
00250                 xstring const& namespace_name,
00251                 /** The name of the attribute */
00252                 xstring const& name,
00253                 /** To be completed: Should be a variant. */
00254                 xstring const& value);
00255 
00256         /// Get an attribute.
00257         const_iterator find(
00258                 /** Can be the uri or a short cut */
00259                 xstring const& namespace_name,
00260                 /** The name of the attribute */
00261                 xstring const& name) const;
00262 
00263 
00264         /// PutTo operator.
00265         xostream& write(xostream& xos) const;
00266 
00267         /// GetFrom operator.
00268         xistream& read(xistream& xis);
00269 
00270 private: // data members
00271         /// map ((uri,name), value).
00272         map_type map_;
00273 
00274         /// map (uri, short_ns).
00275         map_uri_type map_uri_;
00276 }; // end  of the class attributes
00277 
00278 
00279 //-----------------------------------------------------------------------------
00280 /// put to operator for attributes
00281 //-----------------------------------------------------------------------------
00282 inline xostream& operator<<(xostream& xos, attributes const& rhs)
00283 {
00284         return rhs.write(xos);
00285 }
00286 
00287 //-----------------------------------------------------------------------------
00288 /// get from operator for attributes
00289 //-----------------------------------------------------------------------------
00290 inline xistream& operator>>(xistream& xis, attributes& rhs)
00291 {
00292         return rhs.read(xis);
00293 }
00294 
00295 //-----------------------------------------------------------------------------
00296 /// put to operator for attributes on standard stream
00297 //-----------------------------------------------------------------------------
00298 XIMOL_EXPORT ::std::ostream& operator<<(::std::ostream& os, attributes const& x);
00299 
00300 XIMOL_XML_END_NAMESPACE
00301 
00302 XIMOL_BEGIN_NAMESPACE
00303 
00304 //-----------------------------------------------------------------------------
00305 /** insert an attribute
00306  *  @ingroup xml
00307  *  insert a attribute in the attribute list.
00308  *  if the attribute name already exist, nothing is done.
00309  *  If an insertion occurred, the function returns pair(where, true). 
00310  *  Otherwise, it returns pair(it, false).
00311  * 
00312  * 
00313  *  @param att: the attributes list
00314  *  @param namespace_name: the namespace or shortcut for the inserted attribute
00315  *  @param name: the name for the inserted attribute
00316  *  @param value: the value for the inserted attribute (serialize with str<xstring>::cast(value))
00317  *  @return If an insertion occurred, the function returns pair(where, true). Otherwise, it returns pair(it, false).
00318  */
00319 //-----------------------------------------------------------------------------
00320 template<typename StringT1, typename StringT2, typename T>
00321 std::pair<xml::attributes::iterator, bool> // return type
00322 insert_attribute(xml::attributes& att,
00323                                  StringT1 const& namespace_name,
00324                                  StringT2 const& name,
00325                                  T const& value)
00326 {
00327         return att.insert(
00328                 str<xstring>::cast(namespace_name),
00329                 str<xstring>::cast(name),
00330         str<xstring>::cast(value));
00331 }
00332 
00333 //-----------------------------------------------------------------------------
00334 /** insert an attribute
00335  *  @ingroup xml
00336  *  insert a attribute in the attribute list.
00337  *  if the attribute name already exist, nothing is done.
00338  */
00339 //-----------------------------------------------------------------------------
00340 template<typename StringT, typename T>
00341 std::pair<xml::attributes::iterator, bool> // return type
00342 insert_attribute(xml::attributes& att,
00343                                  StringT const& name,
00344                                  T const& value)
00345 {
00346     return insert_attribute(att, L"", name, value);
00347 }
00348 
00349 //-----------------------------------------------------------------------------
00350 /// set an attribute
00351 //-----------------------------------------------------------------------------
00352 template<typename StringT1, typename StringT2, typename T>
00353 void 
00354 set_attribute(xml::attributes& att,
00355                                  StringT1 const& namespace_name,
00356                                  StringT2 const& name,
00357                                  T const& value)
00358 {
00359         att.set(
00360                 str<xstring>::cast(namespace_name),
00361                 str<xstring>::cast(name),
00362         str<xstring>::cast(value));
00363 }
00364 
00365 //-----------------------------------------------------------------------------
00366 /// set an xml::attributes
00367 //-----------------------------------------------------------------------------
00368 template<typename StringT, typename T>
00369 void
00370 set_attribute(xml::attributes& att,
00371                                  StringT const& name,
00372                                  T const& value)
00373 {
00374     set_attribute(att, L"", name, value);
00375 }
00376 
00377 //-----------------------------------------------------------------------------
00378 /**
00379  * Deserialize the attribute value.
00380  */
00381 //-----------------------------------------------------------------------------
00382 template<typename StringT1, typename StringT2, typename T>
00383 bool get_attribute(xml::attributes const& att,
00384                                    StringT1 const& namespace_name,
00385                                    StringT2 const& name,
00386                                    /**
00387                                         * Type requirements: copy constructable, serializable.
00388                                         * T doesn't need to be default constructable.
00389                                     */
00390                                    T& value)
00391 {
00392         xml::attributes::const_iterator const i_value = att.find(
00393                 str< ::std::wstring>::cast(namespace_name),
00394                 str< ::std::wstring>::cast(name));
00395 
00396         if(i_value != att.end()) {
00397                 ::std::basic_istringstream<xchar_t> is(i_value->second+L" *");
00398 
00399                 T temp(value); // copy constructable
00400                 is >> temp;
00401 
00402                 if(is.good()) {
00403                         std::swap(temp, value);
00404                         return true;
00405                 }
00406         }
00407 
00408         return false;
00409 }
00410 
00411 /**
00412  * Deserialize the attribute from the name.
00413  */
00414 template<typename StringT, typename T>
00415 bool get_attribute(xml::attributes const& att, StringT const& name, T& value)
00416 {
00417         return get_attribute(att, L"", name, value);
00418 }
00419 
00420 /**
00421  * Deserialize the attribute from the name.
00422  */
00423 template<typename StringT1, typename StringT2 >
00424 xstring get_raw_attribute(xml::attributes const& att, StringT1 const& namespace_name, StringT2 const& name)
00425 {
00426         xml::attributes::const_iterator const i_value = att.find(
00427                 str< ::std::wstring>::cast(namespace_name),
00428                 str< ::std::wstring>::cast(name));
00429 
00430         if(i_value != att.end()) return i_value->second;
00431 
00432         return L"";
00433 }
00434 
00435 /**
00436  * Deserialize the attribute from the name.
00437  */
00438 template<typename StringT>
00439 xstring get_raw_attribute(xml::attributes const& att, StringT const& name)
00440 {
00441         return get_raw_attribute(att, L"", name);
00442 }
00443 
00444 /**
00445  * Deserialize the attribute from the name.
00446  */
00447 template < typename T>
00448 struct extract_attribute
00449 {
00450     template <typename StringT>
00451     static T get(xml::attributes const& att, StringT const& name)
00452     {
00453         T result;
00454         get_attribute(att, name, result);
00455         return result;
00456     };
00457     template <typename StringT1, typename StringT2>
00458     static T get(xml::attributes const& att, StringT1 const& namespace_name, StringT2 const& name)
00459     {
00460         T result;
00461         get_attribute(att, namespace_name, name, result);
00462         return result;
00463     };
00464 };
00465 
00466 //-----------------------------------------------------------------------------
00467 /**
00468  * Deserialize the attribute from the name.
00469  */
00470 //-----------------------------------------------------------------------------
00471 template <>
00472 struct extract_attribute<std::string>
00473 {
00474     template <typename StringT>
00475     static std::string get(xml::attributes const& att, StringT const& name)
00476     {
00477         return str<std::string>::cast(get_raw_attribute(att, name));
00478     };
00479     template <typename StringT1, typename StringT2>
00480     static std::string get(xml::attributes const& att, StringT1 const& namespace_name, StringT2 const& name)
00481     {
00482         return str<std::string>::cast(get_raw_attribute(att, namespace_name, name));
00483     };
00484 };
00485 
00486 //-----------------------------------------------------------------------------
00487 /**
00488  * Deserialize the attribute from the name.
00489  */
00490 //-----------------------------------------------------------------------------
00491 template <>
00492 struct extract_attribute<std::wstring>
00493 {
00494     template <typename StringT>
00495     static std::wstring get(xml::attributes const& att, StringT const& name)
00496     {
00497         return str<std::wstring>::cast(get_raw_attribute(att, name));
00498     };
00499     template <typename StringT1, typename StringT2>
00500     static std::wstring get(xml::attributes const& att, StringT1 const& namespace_name, StringT2 const& name)
00501     {
00502         return str<std::wstring>::cast(get_raw_attribute(att, namespace_name, name));
00503     };
00504 };
00505 
00506 //-----------------------------------------------------------------------------
00507 /** define a short_namespace for an uri.
00508   * @param att the xml::attributes.
00509   * @param short_namespace the short cut  
00510   * @param uri the namespace or uri.  
00511   */
00512 //-----------------------------------------------------------------------------
00513 template < typename String1, typename String2>
00514 bool set_namespace(xml::attributes & att, String1 & short_namespace, const String2 & uri)
00515 {
00516     return att.insert_namespace(str< ::std::wstring>::cast(short_namespace), str< ::std::wstring>::cast(uri)).second;
00517 }
00518 
00519 //-----------------------------------------------------------------------------
00520 /** define the default namespace.
00521   * @param att the xml::attributes.
00522   * @param uri the futur default namespace.  
00523   */
00524 //-----------------------------------------------------------------------------
00525 template < typename String >
00526 void set_namespace(xml::attributes & att, const String & uri)
00527 {
00528     att.set_namespace(str< ::std::wstring>::cast(uri));
00529 }
00530 
00531 //-----------------------------------------------------------------------------
00532 /** Get the uri from the short namespace.
00533   * @param att the xml::attributes.
00534   * @param short_namespace the short namespace.
00535   * @return the uri or the short_namespace (in input) if the uri is not found. 
00536   */
00537 //-----------------------------------------------------------------------------
00538 template < typename String >
00539 xstring get_namespace(xml::attributes & att, String & short_namespace)
00540 {
00541     xml::attributes::const_ns_iterator i=att.find_namespace(str< ::std::wstring>::cast(short_namespace));
00542     if (i==att.ns_end())
00543         return str<xstring>::cast(short_namespace);
00544     return i->first;
00545 }
00546 
00547 //-----------------------------------------------------------------------------
00548 /** get the default namespace.
00549   * @param att the xml::attributes.
00550   * @return return the default namespace of the xml::attributes.
00551   */
00552 //-----------------------------------------------------------------------------
00553 inline xstring get_namespace(xml::attributes & att)
00554 {
00555     xml::attributes::const_ns_iterator i=att.find_namespace();
00556     if (i==att.ns_end())
00557         return L"";
00558     return i->first;
00559 }
00560 
00561 //-----------------------------------------------------------------------------
00562 /** get the uri from the short namespace.
00563   * This template version call the internal function of the xml::attributes.
00564   *
00565   * @param att the xml::attributes.
00566   * @param uri the long version of the namespace.
00567   * @return the short namespace or the uri (in input) if the short namespace is not found. 
00568   */
00569 //-----------------------------------------------------------------------------
00570 template < typename String >
00571 xstring get_short_namespace(xml::attributes & att, String & uri)
00572 {
00573     xml::attributes::const_ns_iterator i=att.find_short_namespace(str< ::std::wstring>::cast(uri));
00574     if (i==att.ns_end())
00575         return str<xstring>::cast(uri);
00576     return i->second;
00577 }
00578 
00579 XIMOL_END_NAMESPACE
00580 
00581 #endif // #ifndef XIMOL_ATTRIBUTES_HPP_


Donate to the XiMoL project SourceForge.net Logo If you have any questions about XiMoL, you could write to tournois@users.sourceforge.net.