1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/base/Xml.h
12 #ifndef ZYPP_BASE_XML_H
13 #define ZYPP_BASE_XML_H
22 #include "zypp/base/Easy.h"
23 #include "zypp/base/String.h"
24 #include "zypp/parser/xml/XmlEscape.h"
26 ///////////////////////////////////////////////////////////////////
29 ///////////////////////////////////////////////////////////////////
35 /** \relates NodeAttr NODE ATTRIBUTE representation of types [str::asString] */
37 std::string asXmlNodeAttr( const _Tp & val_r )
38 { return str::asString( val_r ); }
40 ///////////////////////////////////////////////////////////////////
42 /// \brief (Key, Value) string pair of XML node attributes
43 struct NodeAttr : public std::pair<std::string,std::string>
45 typedef std::pair<std::string,std::string> Pair;
47 template <typename _Type>
48 NodeAttr( std::string key_r, const _Type & val_r )
49 : Pair( std::move(key_r), asXmlNodeAttr(val_r) )
52 NodeAttr( std::string key_r, std::string val_r )
53 : Pair( std::move(key_r), std::move(val_r) )
56 ///////////////////////////////////////////////////////////////////
58 ///////////////////////////////////////////////////////////////////
60 /// \brief RAII writing a nodes start/end tag
63 /// Node node( std::cout, "node", { "attr", "val" } ); // <node attr="val">
64 /// *node << "write nodes body...."
67 /// \note If the \ref optionalContent flag is passed to the \c ctor, the start
68 /// node is kept open, until the first call to \ref operator*. The start node
69 /// is closed before returning the stream.
72 /// Node node( std::cout, "node", Node::optionalContent, { "attr", "val" } );
73 /// // <node attr="val"
76 /// Node node( std::cout, "node", Node::optionalContent, { "attr", "val" } );
77 /// // <node attr="val"
78 /// *node << "write nodes body...." // />write nodes body...
84 NON_COPYABLE_BUT_MOVE( Node );
85 typedef NodeAttr Attr;
87 struct OptionalContentType {}; ///< Ctor arg type
88 static constexpr OptionalContentType optionalContent = OptionalContentType();
90 /** Ctor taking nodename and attribute list */
91 Node( std::ostream & out_r, std::string name_r, const std::initializer_list<Attr> & attrs_r = {} )
92 : _out( out_r ), _name( std::move(name_r) ), _hasContent( true )
93 { printStart( attrs_r ); }
95 /** Convenience ctor for one attribute pair */
96 Node( std::ostream & out_r, std::string name_r, Attr attr_r )
97 : Node( out_r, std::move(name_r), { attr_r } )
100 /** Optional content ctor taking nodename and attribute list */
101 Node( std::ostream & out_r, std::string name_r, OptionalContentType, const std::initializer_list<Attr> & attrs_r = {} )
102 : _out( out_r ), _name( std::move(name_r) ), _hasContent( false )
103 { printStart( attrs_r ); }
105 /** Optional content Convenience ctor for one attribute pair */
106 Node( std::ostream & out_r, std::string name_r, OptionalContentType, Attr attr_r )
107 : Node( out_r, std::move(name_r), optionalContent, { attr_r } )
110 /** Dtor wrting end tag */
113 if ( ! _name.empty() )
116 _out << "</" << _name << ">";
122 /** Return the output stream */
123 std::ostream & operator*()
128 if ( ! _name.empty() )
135 void printStart( const std::initializer_list<Attr> & attrs_r )
137 if ( ! _name.empty() )
139 _out << "<" << _name;
140 for ( const auto & pair : attrs_r )
141 _out << " " << pair.first << "=\"" << xml::escape( pair.second ) << "\"";
151 ///////////////////////////////////////////////////////////////////
153 /** \relates Node Write a leaf node without PCDATA
158 inline std::ostream & node( std::ostream & out_r, const std::string & name_r, const std::initializer_list<Node::Attr> & attrs_r = {} )
160 Node( out_r, name_r, Node::optionalContent, attrs_r );
163 /** \overload for one attribute pair */
164 inline std::ostream & node( std::ostream & out_r, const std::string & name_r, Node::Attr attr_r )
165 { return node( out_r, name_r, { attr_r } ); }
167 } // namespace xmlout
168 ///////////////////////////////////////////////////////////////////
170 ///////////////////////////////////////////////////////////////////
171 #endif // ZYPP_BASE_XML_H