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 ); }
///////////////////////////////////////////////////////////////////
{
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) )
{}
/** Dtor wrting end tag */
~Node()
{
- if ( _name.empty() )
+ if ( isComment() )
_out << "-->";
else
{
}
}
+ /** 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 << ">";
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;
/// \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;
}
//@}