A toolkit for working with phylogenetic data.
v0.24.0
utils/formats/xml/writer.cpp
Go to the documentation of this file.
1 /*
2  Genesis - A toolkit for working with phylogenetic data.
3  Copyright (C) 2014-2020 Lucas Czech and HITS gGmbH
4 
5  This program is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  Contact:
19  Lucas Czech <lucas.czech@h-its.org>
20  Exelixis Lab, Heidelberg Institute for Theoretical Studies
21  Schloss-Wolfsbrunnenweg 35, D-69118 Heidelberg, Germany
22 */
23 
32 
39 
40 #include <cassert>
41 #include <stdexcept>
42 
43 namespace genesis {
44 namespace utils {
45 
46 // =================================================================================================
47 // Printing
48 // =================================================================================================
49 
50 void XmlWriter::write( XmlDocument const& document, std::shared_ptr<utils::BaseOutputTarget> target ) const
51 {
52  auto& os = target->ostream();
53 
54  if( !document.xml_tag.empty() || !document.declarations.empty() ) {
55  os << "<?" << document.xml_tag << print_attributes_list_(document.declarations) << "?>\n";
56  }
57  print_element_( &document, 0, os );
58  os << "\n";
59 }
60 
61 // =================================================================================================
62 // Internal
63 // =================================================================================================
64 
68 void XmlWriter::print_comment_( XmlComment const* value, std::ostream& os ) const
69 {
70  os << xml_comment( value->content );
71 }
72 
76 void XmlWriter::print_markup_( XmlMarkup const* value, std::ostream& os ) const
77 {
78  os << xml_escape(value->content);
79 }
80 
84 void XmlWriter::print_element_( XmlElement const* value, const int indent_level, std::ostream& os ) const
85 {
86  // Prepare indention and opening tag.
87  std::string in0 (indent_level * indent, ' ');
88  os << in0 << "<" << value->tag << print_attributes_list_(value->attributes);
89 
90  // If it's an empty element, close it, and we are done.
91  if (value->content.size() == 0) {
92  os << " />";
93  return;
94  }
95 
96  // If the element only contains a single markup, don't add new lines. However, if it contains
97  // more data, put each element in a new line.
98  os << ">";
99  if (value->content.size() == 1 && value->content[0]->is_markup()) {
100  print_markup_( xml_value_to_markup(value->content[0].get()), os );
101  } else {
102  std::string in1 ((indent_level + 1) * indent, ' ');
103  os << "\n";
104 
105  for (auto& v : value->content) {
106  if (v->is_comment()) {
107  os << in1;
108  print_comment_( xml_value_to_comment(v.get()), os );
109  } else if (v->is_markup()) {
110  os << in1;
111  print_markup_( xml_value_to_markup(v.get()), os );
112  } else if (v->is_element()) {
113  print_element_( xml_value_to_element(v.get()), indent_level + 1, os );
114  } else {
115  // there are no other cases
116  assert(0);
117  }
118  os << "\n";
119  }
120  os << in0;
121  }
122 
123  os << "</" << value->tag << ">";
124 }
125 
129 std::string XmlWriter::print_attributes_list_ (StringMapType attr) const
130 {
131  std::string xml;
132  for (auto pair : attr) {
133  xml += xml_attribute( pair.first, pair.second );
134  // xml += " " + pair.first + "=\"" + pair.second + "\"";
135  }
136  return xml;
137 }
138 
139 } // namespace utils
140 } // namespace genesis
void print_comment_(XmlComment const *value, std::ostream &os) const
Print an XML comment.
std::string print_attributes_list_(StringMapType attr) const
Print a list of XML attributes.
void print_element_(XmlElement const *value, const int indent_level, std::ostream &os) const
Print an XML element.
int indent
Indent used for printing the XML elements.
const XmlComment * xml_value_to_comment(const XmlValue *v)
Converts a pointer to an XmlValue to XmlComment if appropriate.
std::string xml_escape(std::string const &txt)
Escape special XML characters.
Container namespace for all symbols of genesis in order to keep them separate when used as a library...
const XmlElement * xml_value_to_element(const XmlValue *v)
Converts a pointer to an XmlValue to XmlElement if appropriate.
std::string xml_attribute(std::string const &name, T const &value)
const XmlMarkup * xml_value_to_markup(const XmlValue *v)
Converts a pointer to an XmlValue to XmlMarkup if appropriate.
A collection of classes for working with XML documents. See XmlDocument for more. ...
Provides some commonly used string utility functions.
Provides functions for accessing the file system.
Provides easy and fast logging functionality.
std::vector< std::unique_ptr< XmlValue > > content
void print_markup_(XmlMarkup const *value, std::ostream &os) const
Print an XML markup (simple text).
std::string xml_comment(std::string const &content)
void write(XmlDocument const &document, std::shared_ptr< utils::BaseOutputTarget > target) const