// file      : xsd/cxx/tree/types.hxx
// author    : Boris Kolpackov <boris@codesynthesis.com>
// copyright : Copyright (c) 2005 Code Synthesis Tools CC
// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file

#ifndef XSD_CXX_TREE_TYPES_HXX
#define XSD_CXX_TREE_TYPES_HXX

#include <cstdlib> // std::size_t
#include <string>
#include <ostream>

#include <xsd/cxx/xml/dom/elements.hxx>

#include <xsd/cxx/tree/elements.hxx>

namespace xsd
{
  namespace cxx
  {
    namespace tree
    {
      // string
      //
      template <typename C>
      class string_template: public std::basic_string<C>,
                             public simple_type

      {
      protected:
        typedef std::basic_string<C> primary_type;
        typedef std::basic_string<C> base_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        string_template ()
        {
        }

        string_template (C const* s)
            : base_type (s)
        {
        }

        string_template (C const* s, std::size_t n)
            : base_type (s, n)
        {
        }

        string_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        string_template (primary_type const& str)
            : base_type (str)
        {
        }

        string_template (primary_type const& str,
                         std::size_t pos,
                         std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        string_template (string_template const& other,
                         flags f = 0,
                         type* container = 0)
            : base_type (other),
              simple_type (other, f, container)
        {
        }

      public:
        explicit
        string_template (xml::dom::element<C> const& e,
                         flags f,
                         type* container)
            : base_type (e.value ()), simple_type (e, f, container)
        {
        }

        explicit
        string_template (xml::dom::attribute<C> const& a,
                         flags f,
                         type* container)
            : base_type (a.value ()), simple_type (a, f, container)
        {
        }

        string_template (std::basic_string<C> const& s,
                         xml::dom::element<C> const& e,
                         flags f,
                         type* container)
            : base_type (s), simple_type (s, e, f, container)
        {
        }

      public:
        string_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        string_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        string_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };

      template <typename C>
      inline std::basic_ostream<C>&
      operator<< (std::basic_ostream<C>& os, string_template<C> const& v)
      {
        std::basic_string<C> const& r (v);
        return os << r;
      }


      // normalized_string: string
      //
      template <typename C>
      class normalized_string_template: public string_template<C>
      {
      protected:
        typedef string_template<C> base_type;
        typedef typename base_type::primary_type primary_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        normalized_string_template ()
        {
        }

        normalized_string_template (C const* s)
            : base_type (s)
        {
        }

        normalized_string_template (C const* s, std::size_t n)
            : base_type (s, n)
        {
        }

        normalized_string_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        normalized_string_template (primary_type const& str)
            : base_type (str)
        {
        }

        normalized_string_template (primary_type const& str,
                                    std::size_t pos,
                                    std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        normalized_string_template (
          normalized_string_template const& other,
          flags f = 0,
          type* container = 0)
            : base_type (other, f, container)
        {
        }

      public:
        explicit
        normalized_string_template (xml::dom::element<C> const& e,
                                    flags f,
                                    type* container)
            : base_type (e, f, container)
        {
        }

        explicit
        normalized_string_template (xml::dom::attribute<C> const& a,
                                    flags f,
                                    type* container)
            : base_type (a, f, container)
        {
        }

        normalized_string_template (std::basic_string<C> const& s,
                                    xml::dom::element<C> const& e,
                                    flags f,
                                    type* container)
            : base_type (s, e, f, container)
        {
        }

      public:
        normalized_string_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        normalized_string_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        normalized_string_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };

      template <typename C>
      inline std::basic_ostream<C>&
      operator<< (std::basic_ostream<C>& os,
                  normalized_string_template<C> const& v)
      {
        string_template<C> const& r (v);
        return os << r;
      }


      // token: normalized_string
      //
      template <typename C>
      class token_template: public normalized_string_template<C>
      {
      protected:
        typedef normalized_string_template<C> base_type;
        typedef typename base_type::primary_type primary_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        token_template ()
        {
        }

        token_template (C const* s)
            : base_type (s)
        {
        }

        token_template (C const* s, std::size_t n)
            : base_type (s, n)
        {
        }

        token_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        token_template (primary_type const& str)
            : base_type (str)
        {
        }

        token_template (primary_type const& str,
                        std::size_t pos,
                        std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        token_template (token_template const& other,
                        flags f = 0,
                        type* container = 0)
            : base_type (other, f, container)
        {
        }

      public:
        explicit
        token_template (xml::dom::element<C> const& e,
                        flags f,
                        type* container)
            : base_type (e, f, container)
        {
        }

        explicit
        token_template (xml::dom::attribute<C> const& a,
                        flags f,
                        type* container)
            : base_type (a, f, container)
        {
        }

        token_template (std::basic_string<C> const& s,
                        xml::dom::element<C> const& e,
                        flags f,
                        type* container)
            : base_type (s, e, f, container)
        {
        }

      public:
        token_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        token_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        token_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };

      template <typename C>
      inline std::basic_ostream<C>&
      operator<< (std::basic_ostream<C>& os, token_template<C> const& v)
      {
        normalized_string_template<C> const& r (v);
        return os << r;
      }


      // nmtoken: token
      //
      template <typename C>
      class nmtoken_template: public token_template<C>
      {
      protected:
        typedef token_template<C> base_type;
        typedef typename base_type::primary_type primary_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        nmtoken_template (C const* s)
            : base_type (s)
        {
        }

        nmtoken_template (C const* s, std::size_t n)
            : base_type (s, n)
        {
        }

        nmtoken_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        nmtoken_template (primary_type const& str)
            : base_type (str)
        {
        }

        nmtoken_template (primary_type const& str,
                          std::size_t pos,
                          std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        nmtoken_template (nmtoken_template const& other,
                          flags f = 0,
                          type* container = 0)
            : base_type (other, f, container)
        {
        }

      public:
        explicit
        nmtoken_template (xml::dom::element<C> const& e,
                          flags f,
                          type* container)
            : base_type (e, f, container)
        {
        }

        explicit
        nmtoken_template (xml::dom::attribute<C> const& a,
                          flags f,
                          type* container)
            : base_type (a, f, container)
        {
        }

        nmtoken_template (std::basic_string<C> const& s,
                          xml::dom::element<C> const& e,
                          flags f,
                          type* container)
            : base_type (s, e, f, container)
        {
        }

      public:
        nmtoken_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        nmtoken_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        nmtoken_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };


      template <typename C>
      inline std::basic_ostream<C>&
      operator<< (std::basic_ostream<C>& os, nmtoken_template<C> const& v)
      {
        token_template<C> const& r (v);
        return os << r;
      }


      // nmtokens: sequence<nmtoken>
      //
      template <typename C>
      class nmtokens_template: public simple_type,
                               public sequence<nmtoken_template<C> >
      {
        typedef sequence<nmtoken_template<C> > base_type;

      public:
        nmtokens_template ()
        {
        }

        nmtokens_template (nmtokens_template const& other,
                           flags f,
                           type* container)
            : simple_type (other, f, container),
              base_type (other, f, container)
        {
        }

      public:
        explicit
        nmtokens_template (xml::dom::element<C> const& e,
                           flags f,
                           type* container)
            : simple_type (e, f, container), base_type (e, f, container)
        {
        }

        explicit
        nmtokens_template (xml::dom::attribute<C> const& a,
                           flags f,
                           type* container)
            : simple_type (a, f, container), base_type (a, f, container)
        {
        }

        nmtokens_template (std::basic_string<C> const& s,
                           xml::dom::element<C> const& e,
                           flags f,
                           type* container)
            : simple_type (s, e, f, container),
              base_type (s, e, f, container)
        {
        }
      };

      template <typename C>
      inline std::basic_ostream<C>&
      operator<< (std::basic_ostream<C>& os, nmtokens_template<C> const& v)
      {
        sequence<nmtoken_template<C> > const& r (v);
        return os << r;
      }


      // name: token
      //
      template <typename C>
      class name_template: public token_template<C>
      {
      protected:
        typedef token_template<C> base_type;
        typedef typename base_type::primary_type primary_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        name_template (C const* s)
            : base_type (s)
        {
        }

        name_template (C const* s, std::size_t n)
            : base_type (s, n)
        {
        }

        name_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        name_template (primary_type const& str)
            : base_type (str)
        {
        }

        name_template (primary_type const& str,
                       std::size_t pos,
                       std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        name_template (name_template const& other,
                       flags f = 0,
                       type* container = 0)
            : base_type (other, f, container)
        {
        }

      public:
        explicit
        name_template (xml::dom::element<C> const& e,
                       flags f,
                       type* container)
            : base_type (e, f, container)
        {
        }

        explicit
        name_template (xml::dom::attribute<C> const& a,
                       flags f,
                       type* container)
            : base_type (a, f, container)
        {
        }

        name_template (std::basic_string<C> const& s,
                       xml::dom::element<C> const& e,
                       flags f,
                       type* container)
            : base_type (s, e, f, container)
        {
        }

      public:
        name_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        name_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        name_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };

      template <typename C>
      inline std::basic_ostream<C>&
      operator<< (std::basic_ostream<C>& os, name_template<C> const& v)
      {
        token_template<C> const& r (v);
        return os << r;
      }


      // ncname: name
      //
      template <typename C>
      class ncname_template: public name_template<C>
      {
      protected:
        typedef name_template<C> base_type;
        typedef typename base_type::primary_type primary_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        ncname_template (C const* s)
            : base_type (s)
        {
        }

        ncname_template (C const* s, std::size_t n)
            : base_type (s, n)
        {
        }

        ncname_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        ncname_template (primary_type const& str)
            : base_type (str)
        {
        }

        ncname_template (primary_type const& str,
                         std::size_t pos,
                         std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        ncname_template (ncname_template const& other,
                         flags f = 0,
                         type* container = 0)
            : base_type (other, f, container)
        {
        }

      public:
        explicit
        ncname_template (xml::dom::element<C> const& e,
                         flags f,
                         type* container)
            : base_type (e, f, container)
        {
        }

        explicit
        ncname_template (xml::dom::attribute<C> const& a,
                         flags f,
                         type* container)
            : base_type (a, f, container)
        {
        }

        ncname_template (std::basic_string<C> const& s,
                         xml::dom::element<C> const& e,
                         flags f,
                         type* container)
            : base_type (s, e, f, container)
        {
        }

      public:
        ncname_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        ncname_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        ncname_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //

      };

      template <typename C>
      inline std::basic_ostream<C>&
      operator<< (std::basic_ostream<C>& os, ncname_template<C> const& v)
      {
        name_template<C> const& r (v);
        return os << r;
      }


      // language: token
      //
      template <typename C>
      class language_template: public token_template<C>
      {
      protected:
        typedef token_template<C> base_type;
        typedef typename base_type::primary_type primary_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        language_template (C const* s)
            : base_type (s)
        {
        }

        language_template (C const* s, std::size_t n)
            : base_type (s, n)
        {
        }

        language_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        language_template (primary_type const& str)
            : base_type (str)
        {
        }

        language_template (primary_type const& str,
                           std::size_t pos,
                           std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        language_template (language_template const& other,
                           flags f = 0,
                           type* container = 0)
            : base_type (other, f, container)
        {
        }

      public:
        explicit
        language_template (xml::dom::element<C> const& e,
                           flags f,
                           type* container)
            : base_type (e, f, container)
        {
        }

        explicit
        language_template (xml::dom::attribute<C> const& a,
                           flags f,
                           type* container)
            : base_type (a, f, container)
        {
        }

        language_template (std::basic_string<C> const& s,
                           xml::dom::element<C> const& e,
                           flags f,
                           type* container)
            : base_type (s, e, f, container)
        {
        }

      public:
        language_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        language_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        language_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };

      template <typename C>
      inline std::basic_ostream<C>&
      operator<< (std::basic_ostream<C>& os, language_template<C> const& v)
      {
        token_template<C> const& r (v);
        return os << r;
      }


      //
      //
      template <typename C>
      struct identity_impl: identity
      {
        identity_impl (ncname_template<C> const& id)
            : id_ (id)
        {
        }

        virtual bool
        before (identity const& y) const
        {
          return id_ < dynamic_cast<identity_impl const&> (y).id_;
        }

        virtual void
        throw_duplicate_id () const
        {
          throw duplicate_id<C> (id_);
        }

      private:
        ncname_template<C> const& id_;
      };


      // id: ncname
      //
      template <typename C>
      class id_template: public ncname_template<C>
      {
      protected:
        typedef ncname_template<C> base_type;
        typedef typename base_type::primary_type primary_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;
        using base_type::empty;

      public:
        ~id_template()
        {
          unregister_id ();
        }

      public:
        id_template (C const* s)
            : base_type (s), identity_ (*this)
        {
          register_id ();
        }

        id_template (C const* s, std::size_t n)
            : base_type (s, n), identity_ (*this)
        {
          register_id ();
        }

        id_template (std::size_t n, C c)
            : base_type (n, c), identity_ (*this)
        {
          register_id ();
        }

        id_template (primary_type const& str)
            : base_type (str), identity_ (*this)
        {
          register_id ();
        }

        id_template (primary_type const& str,
                     std::size_t pos,
                     std::size_t n = npos)
            : base_type (str, pos, n), identity_ (*this)
        {
          register_id ();
        }

      public:
        id_template (id_template const& other,
                     flags f = 0,
                     type* container = 0)
            : base_type (other, f, container), identity_ (*this)
        {
          register_id ();
        }

      public:
        explicit
        id_template (xml::dom::element<C> const& e,
                     flags f,
                     type* container)
            : base_type (e, f, container), identity_ (*this)
        {
          register_id ();
        }

        explicit
        id_template (xml::dom::attribute<C> const& a,
                     flags f,
                     type* container)
            : base_type (a, f, container), identity_ (*this)
        {
          register_id ();
        }

        id_template (std::basic_string<C> const& s,
                     xml::dom::element<C> const& e,
                     flags f,
                     type* container)
            : base_type (s, e, f, container), identity_ (*this)
        {
          register_id ();
        }

      public:
        id_template&
        operator= (C c)
        {
          unregister_id ();
          base () = c;
          register_id ();

          return *this;
        }

        id_template&
        operator= (C const* s)
        {
          unregister_id ();
          base () = s;
          register_id ();

          return *this;
        }

        id_template&
        operator= (primary_type const& str)
        {
          unregister_id ();
          base () = str;
          register_id ();

          return *this;
        }

        id_template&
        operator= (id_template const& str)
        {
          unregister_id ();
          base () = str;
          register_id ();

          return *this;
        }

      public:
        using base_type::_container;

      private:
        void
        register_id ()
        {
          if (_container () != this && !empty ())
          {
            //std::cerr << "registering " << container ()
            //          << " as '" << *this
            //          << "' on " << container () << std::endl;
            _container ()->_register_id (identity_, _container ());
          }
        }

        void
        unregister_id ()
        {
          if (_container () != this && !empty ())
          {
            //std::cerr << "un-registering " << container ()
            //          << " as '" << *this
            //          << "' on " << container () << std::endl;
            _container ()->_unregister_id (identity_);
          }
        }

      private:
        identity_impl<C> identity_;
      };

      template <typename C>
      inline std::basic_ostream<C>&
      operator<< (std::basic_ostream<C>& os, id_template<C> const& v)
      {
        ncname_template<C> const& r (v);
        return os << r;
      }


      // idref: ncname
      //
      template <typename X, typename C>
      class idref_template: public ncname_template<C>
      {
      protected:
        typedef ncname_template<C> base_type;
        typedef typename base_type::primary_type primary_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        typedef X type;

      public:
        using base_type::npos;
        using base_type::empty;

      public:
        idref_template (C const* s)
            : base_type (s), identity_ (*this)
        {
        }

        idref_template (C const* s, std::size_t n)
            : base_type (s, n), identity_ (*this)
        {
        }

        idref_template (std::size_t n, C c)
            : base_type (n, c), identity_ (*this)
        {
        }

        idref_template (primary_type const& str)
            : base_type (str), identity_ (*this)
        {
        }

        idref_template (primary_type const& str,
                        std::size_t pos,
                        std::size_t n = npos)
            : base_type (str, pos, n), identity_ (*this)
        {
        }

      public:
        idref_template (idref_template const& other,
                        flags f = 0,
                        tree::type* container = 0)
            : base_type (other, f, container), identity_ (*this)
        {
        }

      public:
        explicit
        idref_template (xml::dom::element<C> const& e,
                        flags f,
                        tree::type* container)
            : base_type (e, f, container), identity_ (*this)
        {
        }

        explicit
        idref_template (xml::dom::attribute<C> const& a,
                        flags f,
                        tree::type* container)
            : base_type (a, f , container), identity_ (*this)
        {
        }

        idref_template (std::basic_string<C> const& s,
                        xml::dom::element<C> const& e,
                        flags f,
                        tree::type* container)
            : base_type (s, e, f, container), identity_ (*this)
        {
        }

      public:
        idref_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        idref_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        idref_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        idref_template&
        operator= (idref_template const& str)
        {
          base () = str;
          return *this;
        }

      public:
        X const*
        operator-> () const
        {
          return get ();
        }

        X*
        operator-> ()
        {
          return get ();
        }

        X const&
        operator* () const
        {
          return *(get ());
        }

        X&
        operator* ()
        {
          return *(get ());
        }

        X const*
        get () const
        {
          return dynamic_cast<X const*> (get_ ());
        }

        X*
        get ()
        {
          return dynamic_cast<X*> (get_ ());
        }

        // conversion to bool
        //
        typedef void (idref_template::*bool_convertible)();

        operator bool_convertible () const
        {
          return get_ () ? &idref_template::true_ : 0;
        }

      public:
        using base_type::_root;
        using base_type::_container;

      private:
        tree::type const*
        get_ () const
        {
          if (!empty () && _container () != this)
          {
            return _root ()->_lookup_id (identity_);
          }
          else
            return 0;
        }

        tree::type*
        get_ ()
        {
          if (!empty () && _container () != this)
          {
            return _root ()->_lookup_id (identity_);
          }
          else
            return 0;
        }

      private:
        void
        true_ ()
        {
        }

      private:
        identity_impl<C> identity_;
      };

      template <typename X, typename C>
      inline std::basic_ostream<C>&
      operator<< (std::basic_ostream<C>& os, idref_template<X, C> const& v)
      {
        ncname_template<C> const& r (v);
        return os << r;
      }

      // idrefs: sequence<idref>
      //
      template <typename X, typename C>
      class idrefs_template: public simple_type,
                             public sequence<idref_template<X, C> >

      {
        typedef sequence<idref_template<X, C> > base_type;

      public:
        idrefs_template ()
        {
        }

        idrefs_template (idrefs_template const& other,
                         flags f = 0,
                         type* container = 0)
            : simple_type (other, f, container),
              base_type (other, f, container)
        {
        }

      public:
        explicit
        idrefs_template (xml::dom::element<C> const& e,
                         flags f,
                         type* container)
            : simple_type (e, f, container), base_type (e, f, container)
        {
        }

        explicit
        idrefs_template (xml::dom::attribute<C> const& a,
                         flags f,
                         type* container)
            : simple_type (a, f, container), base_type (a, f, container)
        {
        }

        idrefs_template (std::basic_string<C> const& s,
                         xml::dom::element<C> const& e,
                         flags f,
                         type* container)
            : simple_type (s, e, f, container), base_type (s, e, f, container)
        {
        }
      };

      template <typename X, typename C>
      inline std::basic_ostream<C>&
      operator<< (std::basic_ostream<C>& os, idrefs_template<X, C> const& v)
      {
        sequence<idref_template<X, C> > const& r (v);
        return os << r;
      }

      // uri
      //
      template <typename C>
      class uri_template: public std::basic_string<C>,
                          public simple_type
      {
      protected:
        typedef std::basic_string<C> primary_type;
        typedef std::basic_string<C> base_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        uri_template (C const* s)
            : base_type (s)
        {
        }

        uri_template (C const* s, std::size_t n)
            : base_type (s, n)
        {
        }

        uri_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        uri_template (primary_type const& str)
            : base_type (str)
        {
        }

        uri_template (primary_type const& str,
                      std::size_t pos,
                      std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        uri_template (uri_template const& other,
                      flags f = 0,
                      type* container = 0)
            : base_type (other),
              simple_type (other, f, container)
        {
        }

      public:
        explicit
        uri_template (xml::dom::element<C> const& e,
                      flags f,
                      type* container)
            : base_type (e.value ()), simple_type (e, f, container)
        {
        }

        explicit
        uri_template (xml::dom::attribute<C> const& a,
                      flags f,
                      type* container)
            : base_type (a.value ()), simple_type (a, f, container)
        {
        }

        uri_template (std::basic_string<C> const& s,
                      xml::dom::element<C> const& e,
                      flags f,
                      type* container)
            : base_type (s), simple_type (s, e, f, container)
        {
        }

      public:
        uri_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        uri_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        uri_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //

      };

      template <typename C>
      inline std::basic_ostream<C>&
      operator<< (std::basic_ostream<C>& os, uri_template<C> const& v)
      {
        std::basic_string<C> const& r (v);
        return os << r;
      }


      // qname
      //
      template <typename C>
      class qname_template: public simple_type
      {
      public:
        qname_template (uri_template<C> const& ns,
                        ncname_template<C> const& name)
            : ns_ (ns),
              name_ (name)
        {
        }

      public:
        qname_template (qname_template const& other,
                        flags f = 0,
                        type* container = 0)
            : simple_type (other, f, container),
              ns_ (other.ns_),
              name_ (other.name_)
        {
          // Note that ns_ and name_ have no DOM association.
          //
        }

      public:
        explicit
        qname_template (xml::dom::element<C> const& e,
                        flags f,
                        type* container)
            : simple_type (e, f, container),
              ns_ (xml::dom::ns_name (e, e.value ())),
              name_ (xml::uq_name (e.value ()))
        {
        }

        explicit
        qname_template (xml::dom::attribute<C> const& a,
                        flags f,
                        type* container)
            : simple_type (a, f, container),
              ns_ (xml::dom::ns_name (a.element (), a.value ())),
              name_ (xml::uq_name (a.value ()))
        {
        }

        qname_template (std::basic_string<C> const& s,
                        xml::dom::element<C> const& e,
                        flags f,
                        type* container)
            : simple_type (s, e, f, container),
              ns_ (xml::dom::ns_name (e, s)),
              name_ (xml::uq_name (s))
        {
        }

      public:
        uri_template<C> const&
        namespace_ () const
        {
          return ns_;
        }

        ncname_template<C> const&
        name () const
        {
          return name_;
        }

      private:
        uri_template<C> ns_;
        ncname_template<C> name_;
      };

      template <typename C>
      inline std::basic_ostream<C>&
      operator<< (std::basic_ostream<C>& os, qname_template<C> const& n)
      {
        return os << n.namespace_ () << C ('#') << n.name ();
      }


      // base64_binary
      //
      template <typename C>
      class base64_binary_template: public std::basic_string<C>,
                                    public simple_type
      {
      protected:
        typedef std::basic_string<C> primary_type;
        typedef std::basic_string<C> base_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        base64_binary_template ()
        {
        }

        base64_binary_template (C const* s)
            : base_type (s)
        {
        }

        base64_binary_template (C const* s, std::size_t n)
            : base_type (s, n)
        {
        }

        base64_binary_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        base64_binary_template (primary_type const& str)
            : base_type (str)
        {
        }

        base64_binary_template (primary_type const& str,
                                std::size_t pos,
                                std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        base64_binary_template (base64_binary_template const& other,
                                flags f = 0,
                                type* container = 0)
            : base_type (other),
              simple_type (other, f, container)
        {
        }

      public:
        explicit
        base64_binary_template (xml::dom::element<C> const& e,
                                flags f,
                                type* container)
            : base_type (e.value ()), simple_type (e, f, container)
        {
        }

        explicit
        base64_binary_template (xml::dom::attribute<C> const& a,
                                flags f,
                                type* container)
            : base_type (a.value ()), simple_type (a, f, container)
        {
        }

        base64_binary_template (std::basic_string<C> const& s,
                                xml::dom::element<C> const& e,
                                flags f,
                                type* container)
            : base_type (s), simple_type (s, e, f, container)
        {
        }

      public:
        base64_binary_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        base64_binary_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        base64_binary_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //

      };

      template <typename C>
      inline std::basic_ostream<C>&
      operator<< (std::basic_ostream<C>& os,
                  base64_binary_template<C> const& v)
      {
        std::basic_string<C> const& r (v);
        return os << r;
      }


      // hex_binary
      //
      template <typename C>
      class hex_binary_template: public std::basic_string<C>,
                                 public simple_type
      {
      protected:
        typedef std::basic_string<C> primary_type;
        typedef std::basic_string<C> base_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        hex_binary_template ()
        {
        }

        hex_binary_template (C const* s)
            : base_type (s)
        {
        }

        hex_binary_template (C const* s, std::size_t n)
            : base_type (s, n)
        {
        }

        hex_binary_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        hex_binary_template (primary_type const& str)
            : base_type (str)
        {
        }

        hex_binary_template (primary_type const& str,
                             std::size_t pos,
                             std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        hex_binary_template (hex_binary_template const& other,
                             flags f = 0,
                             type* container = 0)
            : base_type (other),
              simple_type (other, f, container)
        {
        }

      public:
        explicit
        hex_binary_template (xml::dom::element<C> const& e,
                             flags f,
                             type* container)
            : base_type (e.value ()), simple_type (e, f, container)
        {
        }

        explicit
        hex_binary_template (xml::dom::attribute<C> const& a,
                             flags f,
                             type* container)
            : base_type (a.value ()), simple_type (a, f, container)
        {
        }

        hex_binary_template (std::basic_string<C> const& s,
                             xml::dom::element<C> const& e,
                             flags f,
                             type* container)
            : base_type (s), simple_type (s, e, f, container)
        {
        }

      public:
        hex_binary_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        hex_binary_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        hex_binary_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //

      };

      template <typename C>
      inline std::basic_ostream<C>&
      operator<< (std::basic_ostream<C>& os, hex_binary_template<C> const& v)
      {
        std::basic_string<C> const& r (v);
        return os << r;
      }


      // date
      //
      template <typename C>
      class date_template: public std::basic_string<C>,
                           public simple_type
      {
      protected:
        typedef std::basic_string<C> primary_type;
        typedef std::basic_string<C> base_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        date_template (C const* s)
            : base_type (s)
        {
        }

        date_template (C const* s, std::size_t n)
            : base_type (s, n)
        {
        }

        date_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        date_template (primary_type const& str)
            : base_type (str)
        {
        }

        date_template (primary_type const& str,
                       std::size_t pos,
                       std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        date_template (date_template const& other,
                       flags f = 0,
                       type* container = 0)
            : base_type (other),
              simple_type (other, f, container)
        {
        }

      public:
        explicit
        date_template (xml::dom::element<C> const& e,
                       flags f,
                       type* container)
            : base_type (e.value ()), simple_type (e, f, container)
        {
        }

        explicit
        date_template (xml::dom::attribute<C> const& a,
                       flags f,
                       type* container)
            : base_type (a.value ()), simple_type (a, f, container)
        {
        }

        date_template (std::basic_string<C> const& s,
                       xml::dom::element<C> const& e,
                       flags f,
                       type* container)
            : base_type (s), simple_type (s, e, f, container)
        {
        }

      public:
        date_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        date_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        date_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };

      template <typename C>
      inline std::basic_ostream<C>&
      operator<< (std::basic_ostream<C>& os, date_template<C> const& v)
      {
        std::basic_string<C> const& r (v);
        return os << r;
      }


      // date_time
      //
      template <typename C>
      class date_time_template: public std::basic_string<C>,
                                public simple_type
      {
      protected:
        typedef std::basic_string<C> primary_type;
        typedef std::basic_string<C> base_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        date_time_template (C const* s)
            : base_type (s)
        {
        }

        date_time_template (C const* s, std::size_t n)
            : base_type (s, n)
        {
        }

        date_time_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        date_time_template (primary_type const& str)
            : base_type (str)
        {
        }

        date_time_template (primary_type const& str,
                            std::size_t pos,
                            std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        date_time_template (date_time_template const& other,
                            flags f = 0,
                            type* container = 0)
            : base_type (other),
              simple_type (other, f, container)
        {
        }

      public:
        explicit
        date_time_template (xml::dom::element<C> const& e,
                            flags f,
                            type* container)
            : base_type (e.value ()), simple_type (e, f, container)
        {
        }

        explicit
        date_time_template (xml::dom::attribute<C> const& a,
                            flags f,
                            type* container)
            : base_type (a.value ()), simple_type (a, f, container)
        {
        }

        date_time_template (std::basic_string<C> const& s,
                            xml::dom::element<C> const& e,
                            flags f,
                            type* container)
            : base_type (s), simple_type (s, e, f, container)
        {
        }

      public:
        date_time_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        date_time_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        date_time_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //

      };

      template <typename C>
      inline std::basic_ostream<C>&
      operator<< (std::basic_ostream<C>& os, date_time_template<C> const& v)
      {
        std::basic_string<C> const& r (v);
        return os << r;
      }


      // duration
      //
      template <typename C>
      class duration_template: public std::basic_string<C>,
                               public simple_type
      {
      protected:
        typedef std::basic_string<C> primary_type;
        typedef std::basic_string<C> base_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        duration_template (C const* s)
            : base_type (s)
        {
        }

        duration_template (C const* s, std::size_t n)
            : base_type (s, n)
        {
        }

        duration_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        duration_template (primary_type const& str)
            : base_type (str)
        {
        }

        duration_template (primary_type const& str,
                           std::size_t pos,
                           std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        duration_template (duration_template const& other,
                           flags f = 0,
                           type* container = 0)
            : base_type (other),
              simple_type (other, f, container)
        {
        }

      public:
        explicit
        duration_template (xml::dom::element<C> const& e,
                           flags f,
                           type* container)
            : base_type (e.value ()), simple_type (e, f, container)
        {
        }

        explicit
        duration_template (xml::dom::attribute<C> const& a,
                           flags f,
                           type* container)
            : base_type (a.value ()), simple_type (a, f, container)
        {
        }

        duration_template (std::basic_string<C> const& s,
                           xml::dom::element<C> const& e,
                           flags f,
                           type* container)
            : base_type (s), simple_type (s, e, f, container)
        {
        }

      public:
        duration_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        duration_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        duration_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //

      };

      template <typename C>
      inline std::basic_ostream<C>&
      operator<< (std::basic_ostream<C>& os, duration_template<C> const& v)
      {
        std::basic_string<C> const& r (v);
        return os << r;
      }


      // day
      //
      template <typename C>
      class day_template: public std::basic_string<C>,
                          public simple_type
      {
      protected:
        typedef std::basic_string<C> primary_type;
        typedef std::basic_string<C> base_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        day_template (C const* s)
            : base_type (s)
        {
        }

        day_template (C const* s, std::size_t n)
            : base_type (s, n)
        {
        }

        day_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        day_template (primary_type const& str)
            : base_type (str)
        {
        }

        day_template (primary_type const& str,
                      std::size_t pos,
                      std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        day_template (day_template const& other,
                      flags f = 0,
                      type* container = 0)
            : base_type (other),
              simple_type (other, f, container)
        {
        }

      public:
        explicit
        day_template (xml::dom::element<C> const& e,
                      flags f,
                      type* container)
            : base_type (e.value ()), simple_type (e, f, container)
        {
        }

        explicit
        day_template (xml::dom::attribute<C> const& a,
                      flags f,
                      type* container)
            : base_type (a.value ()), simple_type (a, f, container)
        {
        }

        day_template (std::basic_string<C> const& s,
                      xml::dom::element<C> const& e,
                      flags f,
                      type* container)
            : base_type (s), simple_type (s, e, f, container)
        {
        }

      public:
        day_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        day_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        day_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //

      };

      template <typename C>
      inline std::basic_ostream<C>&
      operator<< (std::basic_ostream<C>& os, day_template<C> const& v)
      {
        std::basic_string<C> const& r (v);
        return os << r;
      }

      // month
      //
      template <typename C>
      class month_template: public std::basic_string<C>,
                            public simple_type
      {
      protected:
        typedef std::basic_string<C> primary_type;
        typedef std::basic_string<C> base_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        month_template (C const* s)
            : base_type (s)
        {
        }

        month_template (C const* s, std::size_t n)
            : base_type (s, n)
        {
        }

        month_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        month_template (primary_type const& str)
            : base_type (str)
        {
        }

        month_template (primary_type const& str,
                        std::size_t pos,
                        std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        month_template (month_template const& other,
                        flags f = 0,
                        type* container = 0)
            : base_type (other), simple_type (other, f, container)
        {
        }

      public:
        explicit
        month_template (xml::dom::element<C> const& e,
                        flags f,
                        type* container)
            : base_type (e.value ()), simple_type (e, f, container)
        {
        }

        explicit
        month_template (xml::dom::attribute<C> const& a,
                        flags f,
                        type* container)
            : base_type (a.value ()), simple_type (a, f, container)
        {
        }

        month_template (std::basic_string<C> const& s,
                        xml::dom::element<C> const& e,
                        flags f,
                        type* container)
            : base_type (s), simple_type (s, e, f, container)
        {
        }

      public:
        month_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        month_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        month_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //

      };

      template <typename C>
      inline std::basic_ostream<C>&
      operator<< (std::basic_ostream<C>& os, month_template<C> const& v)
      {
        std::basic_string<C> const& r (v);
        return os << r;
      }


      // month_day
      //
      template <typename C>
      class month_day_template: public std::basic_string<C>,
                                public simple_type
      {
      protected:
        typedef std::basic_string<C> primary_type;
        typedef std::basic_string<C> base_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        month_day_template (C const* s)
            : base_type (s)
        {
        }

        month_day_template (C const* s, std::size_t n)
            : base_type (s, n)
        {
        }

        month_day_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        month_day_template (primary_type const& str)
            : base_type (str)
        {
        }

        month_day_template (primary_type const& str,
                            std::size_t pos,
                            std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        month_day_template (month_day_template const& other,
                            flags f = 0,
                            type* container = 0)
            : base_type (other),
              simple_type (other, f, container)
        {
        }

      public:
        explicit
        month_day_template (xml::dom::element<C> const& e,
                            flags f,
                            type* container)
            : base_type (e.value ()), simple_type (e, f, container)
        {
        }

        explicit
        month_day_template (xml::dom::attribute<C> const& a,
                            flags f,
                            type* container)
            : base_type (a.value ()), simple_type (a, f, container)
        {
        }

        month_day_template (std::basic_string<C> const& s,
                            xml::dom::element<C> const& e,
                            flags f,
                            type* container)
            : base_type (s), simple_type (s, e, f, container)
        {
        }

      public:
        month_day_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        month_day_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        month_day_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //

      };

      template <typename C>
      inline std::basic_ostream<C>&
      operator<< (std::basic_ostream<C>& os, month_day_template<C> const& v)
      {
        std::basic_string<C> const& r (v);
        return os << r;
      }


      // year
      //
      template <typename C>
      class year_template: public std::basic_string<C>,
                           public simple_type
      {
      protected:
        typedef std::basic_string<C> primary_type;
        typedef std::basic_string<C> base_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        year_template (C const* s)
            : base_type (s)
        {
        }

        year_template (C const* s, std::size_t n)
            : base_type (s, n)
        {
        }

        year_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        year_template (primary_type const& str)
            : base_type (str)
        {
        }

        year_template (primary_type const& str,
                       std::size_t pos,
                       std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        year_template (year_template const& other,
                       flags f = 0,
                       type* container = 0)
            : base_type (other),
              simple_type (other, f, container)
        {
        }

      public:
        explicit
        year_template (xml::dom::element<C> const& e,
                       flags f,
                       type* container)
            : base_type (e.value ()), simple_type (e, f, container)
        {
        }

        explicit
        year_template (xml::dom::attribute<C> const& a,
                       flags f,
                       type* container)
            : base_type (a.value ()), simple_type (a, f, container)
        {
        }

        year_template (std::basic_string<C> const& s,
                       xml::dom::element<C> const& e,
                       flags f,
                       type* container)
            : base_type (s), simple_type (s, e, f, container)
        {
        }

      public:
        year_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        year_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        year_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //

      };

      template <typename C>
      inline std::basic_ostream<C>&
      operator<< (std::basic_ostream<C>& os, year_template<C> const& v)
      {
        std::basic_string<C> const& r (v);
        return os << r;
      }


      // year_month
      //
      template <typename C>
      class year_month_template: public std::basic_string<C>,
                                 public simple_type
      {
      protected:
        typedef std::basic_string<C> primary_type;
        typedef std::basic_string<C> base_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        year_month_template (C const* s)
            : base_type (s)
        {
        }

        year_month_template (C const* s, std::size_t n)
            : base_type (s, n)
        {
        }

        year_month_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        year_month_template (primary_type const& str)
            : base_type (str)
        {
        }

        year_month_template (primary_type const& str,
                             std::size_t pos,
                             std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        year_month_template (year_month_template const& other,
                             flags f = 0,
                             type* container = 0)
            : base_type (other),
              simple_type (other, f, container)
        {
        }

      public:
        explicit
        year_month_template (xml::dom::element<C> const& e,
                             flags f,
                             type* container)
            : base_type (e.value ()), simple_type (e, f, container)
        {
        }

        explicit
        year_month_template (xml::dom::attribute<C> const& a,
                             flags f,
                             type* container)
            : base_type (a.value ()), simple_type (a, f, container)
        {
        }

        year_month_template (std::basic_string<C> const& s,
                             xml::dom::element<C> const& e,
                             flags f,
                             type* container)
            : base_type (s), simple_type (s, e, f, container)
        {
        }

      public:
        year_month_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        year_month_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        year_month_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //

      };

      template <typename C>
      inline std::basic_ostream<C>&
      operator<< (std::basic_ostream<C>& os, year_month_template<C> const& v)
      {
        std::basic_string<C> const& r (v);
        return os << r;
      }


      // time
      //
      template <typename C>
      class time_template: public std::basic_string<C>,
                           public simple_type
      {
      protected:
        typedef std::basic_string<C> primary_type;
        typedef std::basic_string<C> base_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        time_template (C const* s)
            : base_type (s)
        {
        }

        time_template (C const* s, std::size_t n)
            : base_type (s, n)
        {
        }

        time_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        time_template (primary_type const& str)
            : base_type (str)
        {
        }

        time_template (primary_type const& str,
                       std::size_t pos,
                       std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        time_template (time_template const& other,
                       flags f = 0,
                       type* container = 0)
            : base_type (other),
              simple_type (other, f, container)
        {
        }

      public:
        explicit
        time_template (xml::dom::element<C> const& e,
                       flags f,
                       type* container)
            : base_type (e.value ()), simple_type (e, f, container)
        {
        }

        explicit
        time_template (xml::dom::attribute<C> const& a,
                       flags f,
                       type* container)
            : base_type (a.value ()), simple_type (a, f, container)
        {
        }

        time_template (std::basic_string<C> const& s,
                       xml::dom::element<C> const& e,
                       flags f,
                       type* container)
            : base_type (s), simple_type (s, e, f, container)
        {
        }

      public:
        time_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        time_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        time_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //

      };

      template <typename C>
      inline std::basic_ostream<C>&
      operator<< (std::basic_ostream<C>& os, time_template<C> const& v)
      {
        std::basic_string<C> const& r (v);
        return os << r;
      }


      // entity: ncname
      //
      template <typename C>
      class entity_template: public ncname_template<C>
      {
      protected:
        typedef ncname_template<C> base_type;
        typedef typename base_type::primary_type primary_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        entity_template (C const* s)
            : base_type (s)
        {
        }

        entity_template (C const* s, std::size_t n)
            : base_type (s, n)
        {
        }

        entity_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        entity_template (primary_type const& str)
            : base_type (str)
        {
        }

        entity_template (primary_type const& str,
                         std::size_t pos,
                         std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        entity_template (entity_template const& other,
                         flags f = 0,
                         type* container = 0)
            : base_type (other, f, container)
        {
        }

      public:
        explicit
        entity_template (xml::dom::element<C> const& e,
                         flags f,
                         type* container)
            : base_type (e, f, container)
        {
        }

        explicit
        entity_template (xml::dom::attribute<C> const& a,
                         flags f,
                         type* container)
            : base_type (a, f, container)
        {
        }

        entity_template (std::basic_string<C> const& s,
                         xml::dom::element<C> const& e,
                         flags f,
                         type* container)
            : base_type (s, e, f, container)
        {
        }

      public:
        entity_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        entity_template&
        operator= (C const* s)
        {
          base () = s;
          return *this;
        }

        entity_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //

      };

      template <typename C>
      inline std::basic_ostream<C>&
      operator<< (std::basic_ostream<C>& os, entity_template<C> const& v)
      {
        ncname_template<C> const& r (v);
        return os << r;
      }


      // entities: sequence<entity>
      //
      template <typename C>
      class entities_template: public simple_type,
                               public sequence<entity_template<C> >
      {
        typedef sequence<entity_template<C> > base_type;

      public:
        entities_template ()
        {
        }

        entities_template (entities_template const& other,
                           flags f = 0,
                           type* container = 0)
            : simple_type (other, f, container),
              base_type (other, f, container)
        {
        }

      public:
        explicit
        entities_template (xml::dom::element<C> const& e,
                           flags f,
                           type* container)
            : simple_type (e, f, container), base_type (e, f, container)
        {
        }

        explicit
        entities_template (xml::dom::attribute<C> const& a,
                           flags f,
                           type* container)
            : simple_type (a, f, container), base_type (a, f, container)
        {
        }

        entities_template (std::basic_string<C> const& s,
                           xml::dom::element<C> const& e,
                           flags f,
                           type* container)
            : simple_type (s, e, f, container), base_type (s, e, f, container)
        {
        }
      };

      template <typename C>
      inline std::basic_ostream<C>&
      operator<< (std::basic_ostream<C>& os, entities_template<C> const& v)
      {
        sequence<entity_template<C> > const& r (v);
        return os << r;
      }
    }
  }
}

#include <xsd/cxx/tree/types.txx>

#endif  // XSD_CXX_TREE_TYPES_HXX
