A toolkit for working with phylogenetic data.
v0.20.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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-2017 Lucas Czech
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 <assert.h>
41 #include <stdexcept>
42 
43 namespace genesis {
44 namespace utils {
45 
46 // =================================================================================================
47 // Printing
48 // =================================================================================================
49 
58 void XmlWriter::to_file( const XmlDocument& document, const std::string& filename )
59 {
60  std::string xml;
61  to_string( document, xml );
62  utils::file_write(xml, filename);
63 }
64 
68 void XmlWriter::to_string( const XmlDocument& document, std::string& output )
69 {
70  output = to_string(document);
71 }
72 
76 std::string XmlWriter::to_string( const XmlDocument& document )
77 {
78  std::string res = "";
79  if (!document.xml_tag.empty() || !document.declarations.empty()) {
80  res = "<?" + document.xml_tag + print_attributes_list(document.declarations) + "?>\n";
81  }
82  print_element(res, &document, 0);
83  return res + "\n";
84 }
85 
86 // =================================================================================================
87 // Internal
88 // =================================================================================================
89 
93 void XmlWriter::print_comment (std::string& xml, const XmlComment* value)
94 {
95  xml += xml_comment( value->content );
96 }
97 
101 void XmlWriter::print_markup (std::string& xml, const XmlMarkup* value)
102 {
103  xml += xml_escape(value->content);
104 }
105 
109 void XmlWriter::print_element (std::string& xml, const XmlElement* value, const int indent_level)
110 {
111  // Prepare indention and opening tag.
112  std::string in0 (indent_level * indent, ' ');
113  xml += in0 + "<" + value->tag + print_attributes_list(value->attributes);
114 
115  // If it's an empty element, close it, and we are done.
116  if (value->content.size() == 0) {
117  xml += " />";
118  return;
119  }
120 
121  // If the element only contains a single markup, don't add new lines. However, if it contains
122  // more data, put each element in a new line.
123  xml += ">";
124  if (value->content.size() == 1 && value->content[0]->is_markup()) {
125  print_markup(xml, xml_value_to_markup(value->content[0].get()));
126  } else {
127  std::string in1 ((indent_level + 1) * indent, ' ');
128  xml += "\n";
129 
130  for (auto& v : value->content) {
131  if (v->is_comment()) {
132  xml += in1;
133  print_comment(xml, xml_value_to_comment(v.get()));
134  } else if (v->is_markup()) {
135  xml += in1;
136  print_markup(xml, xml_value_to_markup(v.get()));
137  } else if (v->is_element()) {
138  print_element(xml, xml_value_to_element(v.get()), indent_level + 1);
139  } else {
140  // there are no other cases
141  assert(0);
142  }
143  xml += "\n";
144  }
145  xml += in0;
146  }
147 
148  xml += "</" + value->tag + ">";
149 }
150 
154 std::string XmlWriter::print_attributes_list (StringMapType attr)
155 {
156  std::string xml;
157  for (auto pair : attr) {
158  xml += xml_attribute( pair.first, pair.second );
159  // xml += " " + pair.first + "=\"" + pair.second + "\"";
160  }
161  return xml;
162 }
163 
164 } // namespace utils
165 } // namespace genesis
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.
void print_element(std::string &xml, const XmlElement *value, const int indent_level)
Print an XML element.
void to_file(const XmlDocument &document, const std::string &filename)
Write an XML file from an XmlDocument. Return true iff successful.
const XmlElement * xml_value_to_element(const XmlValue *v)
Converts a pointer to an XmlValue to XmlElement if appropriate.
void to_string(const XmlDocument &document, std::string &output)
Give the XML string representation of a XmlDocument.
void print_comment(std::string &xml, const XmlComment *value)
Print an XML comment.
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.
void print_markup(std::string &xml, const XmlMarkup *value)
Print an XML markup (simple text).
Provides easy and fast logging functionality.
std::vector< std::unique_ptr< XmlValue > > content
std::string xml_comment(std::string const &content)
void file_write(std::string const &content, std::string const &filename)
Write the content of a string to a file.
Definition: fs.cpp:96
std::string print_attributes_list(StringMapType attr)
Print a list of XML attributes.