Helper for generating xml output
[platform/upstream/libzypp.git] / zypp / base / Xml.h
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/base/Xml.h
10  *
11 */
12 #ifndef ZYPP_BASE_XML_H
13 #define ZYPP_BASE_XML_H
14
15 #include <iosfwd>
16 #include <string>
17 #include <vector>
18 #include <list>
19 #include <set>
20 #include <map>
21
22 #include "zypp/base/Easy.h"
23 #include "zypp/base/String.h"
24 #include "zypp/parser/xml/XmlEscape.h"
25
26 ///////////////////////////////////////////////////////////////////
27 namespace zypp
28 {
29   ///////////////////////////////////////////////////////////////////
30   namespace xmlout
31   {
32     using xml::escape;
33     using xml::unescape;
34
35     /** \relates NodeAttr NODE ATTRIBUTE representation of types [str::asString] */
36     template <class _Tp>
37     std::string asXmlNodeAttr( const _Tp & val_r )
38     { return str::asString( val_r ); }
39
40     ///////////////////////////////////////////////////////////////////
41     /// \class NodeAttr
42     /// \brief (Key, Value) string pair of XML node attributes
43     struct NodeAttr : public std::pair<std::string,std::string>
44     {
45       typedef std::pair<std::string,std::string> Pair;
46
47       template <typename _Type>
48       NodeAttr( std::string key_r, const _Type & val_r )
49       : Pair( std::move(key_r), asXmlNodeAttr(val_r) )
50       {}
51
52       NodeAttr( std::string key_r, std::string val_r )
53       : Pair( std::move(key_r), std::move(val_r) )
54       {}
55     };
56     ///////////////////////////////////////////////////////////////////
57
58     ///////////////////////////////////////////////////////////////////
59     /// \class Node
60     /// \brief RAII writing a nodes start/end tag
61     /// \code
62     /// {
63     ///   Node node( std::cout, "node", { "attr", "val" } ); // <node attr="val">
64     ///   *node << "write nodes body...."
65     /// }                                                          // </node>
66     /// \endcode
67     struct Node
68     {
69       NON_COPYABLE_BUT_MOVE( Node );
70
71       /** Ctor taking nodename and attribute list */
72       Node( std::ostream & out_r, std::string name_r, const std::initializer_list<NodeAttr> & attrs_r = {} )
73       : _out( out_r ), _name( std::move(name_r) )
74       {
75         if ( ! _name.empty() )
76         {
77           _out << "<" << _name;
78           for ( const auto & pair : attrs_r )
79             _out << " " << pair.first << "=\"" << xml::escape( pair.second ) << "\"";
80           _out << ">";
81         }
82       }
83
84       /** Convenience ctor for one attribute pair */
85       Node( std::ostream & out_r, std::string name_r, NodeAttr attr_r )
86       : Node( out_r, std::move(name_r), { attr_r } )
87       {}
88
89       /** Dtor wrting end tag */
90       ~Node()
91       { _out << "</" << _name << ">"; }
92
93       /** Return the output stream */
94       std::ostream & operator*() { return _out; }
95
96     private:
97       std::ostream & _out;
98       std::string _name;
99     };
100     ///////////////////////////////////////////////////////////////////
101
102     /** \relates Node Write a leaf node without PCDATA
103      * \code
104      * <node attr="val"/>
105      * \endcode
106      */
107     void node( std::ostream & out_r, const std::string & name_r, const std::initializer_list<NodeAttr> & attrs_r = {} )
108     {
109       out_r << "<" << name_r;
110       for ( const auto & pair : attrs_r )
111         out_r << " " << pair.first << "=\"" << xml::escape( pair.second ) << "\"";
112       out_r << "/>";
113     }
114     /** \overload for one attribute pair */
115     void node( const std::string & name_r, NodeAttr attr_r )
116     { node( name_r, { attr_r } ); }
117
118   } // namespace xmlout
119   ///////////////////////////////////////////////////////////////////
120 } // namespace zypp
121 ///////////////////////////////////////////////////////////////////
122 #endif // ZYPP_BASE_XML_H