Imported Upstream version 16.3.2
[platform/upstream/libzypp.git] / zypp / base / Xml.h
index 801decd..533c229 100644 (file)
@@ -33,8 +33,8 @@ namespace zypp
     using xml::unescape;
 
     /** \relates NodeAttr NODE ATTRIBUTE representation of types [asString] */
-    template <class _Tp>
-    std::string asXmlNodeAttr( const _Tp & val_r )
+    template <class Tp>
+    std::string asXmlNodeAttr( const Tp & val_r )
     { return asString( val_r ); }
 
     ///////////////////////////////////////////////////////////////////
@@ -44,8 +44,8 @@ namespace zypp
     {
       typedef std::pair<std::string,std::string> Pair;
 
-      template <typename _Type>
-      NodeAttr( std::string key_r, const _Type & val_r )
+      template <typename Tp>
+      NodeAttr( std::string key_r, const Tp & val_r )
       : Pair( std::move(key_r), asXmlNodeAttr(val_r) )
       {}
 
@@ -112,7 +112,7 @@ namespace zypp
       /** Dtor wrting end tag */
       ~Node()
       {
-       if ( _name.empty() )
+       if ( isComment() )
          _out << "-->";
        else
        {
@@ -123,13 +123,32 @@ namespace zypp
        }
       }
 
+      /** Exception type thrown if attributes are added to a closed start node. */
+      struct HasContentException{};
+
+       /** Add additional attributes (requires OptionalContentType)
+       * \throw HasContentException If start node is already closed
+       */
+      Node & addAttr( const std::initializer_list<Attr> & attrs_r = {} )
+      {
+       if ( _hasContent )
+         throw HasContentException();
+       printAttr( attrs_r );
+       return *this;
+      }
+
+      /** \overload for one */
+      Node & addAttr( const Attr & attr_r )
+      { return addAttr( { attr_r } ); }
+
+
       /** Return the output stream */
       std::ostream & operator*()
       {
        if ( ! _hasContent )
        {
          _hasContent = true;
-         if ( _name.empty() )
+         if ( isComment() )
            _out << "|";
          else
            _out << ">";
@@ -143,17 +162,26 @@ namespace zypp
        if ( _name.empty() || _name[0] == '!' )
        {
          _out << "<!--" << _name;
-         _name.clear();
+         _name.clear();        // a comment
        }
        else
          _out << "<" << _name;
 
-       for ( const auto & pair : attrs_r )
-         _out << " " << pair.first << "=\"" << xml::escape( pair.second ) << "\"";
+       printAttr( attrs_r );
 
-       if ( ! _name.empty() && _hasContent )
+       if ( !isComment() && _hasContent )
          _out << ">";
       }
+
+      void printAttr( const std::initializer_list<Attr> & attrs_r )
+      {
+       for ( const auto & pair : attrs_r )
+         _out << " " << pair.first << "=\"" << xml::escape( pair.second ) << "\"";
+      }
+
+      bool isComment() const
+      { return _name.empty();  }
+
     private:
       std::ostream & _out;
       std::string _name;
@@ -181,12 +209,12 @@ namespace zypp
   /// \name Default dumpAsXmlOn based on asString.
   ///
   //@{
-  template <class _Tp>
-  inline std::ostream & dumpAsXmlOn( std::ostream & str, const _Tp & obj, const std::string & name_r )
+  template <class Tp>
+  inline std::ostream & dumpAsXmlOn( std::ostream & str, const Tp & obj, const std::string & name_r )
   {
     xmlout::Node guard( str, name_r, xmlout::Node::optionalContent );
     const std::string & content( asString( obj ) );
-    if ( ! content.empty() ) *guard << xml::escape( content );
+    if ( ! content.empty() ) *guard << content;
     return str;
   }
   //@}