Teuchos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Teuchos_XMLObjectImplem.cpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Teuchos: Common Tools Package
4 //
5 // Copyright 2004 NTESS and the Teuchos contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #include "Teuchos_XMLObject.hpp"
11 #include "Teuchos_StrUtils.hpp"
12 #include <cstring>
13 
14 using namespace Teuchos;
15 
16 
17 XMLObjectImplem::XMLObjectImplem(const std::string& tag)
18  : tag_(tag), attributes_(), children_(0), content_(0)
19 {;}
20 
22 {
24  TEUCHOS_TEST_FOR_EXCEPTION(rtn==0, std::runtime_error, "XMLObjectImplem::deepCopy()");
25  rtn->attributes_ = attributes_;
26  rtn->content_ = content_;
27 
28  for (int i=0; i<children_.length(); i++)
29  {
30  rtn->addChild(children_[i].deepCopy());
31  }
32 
33  return rtn;
34 }
35 
37 {
38  return children_.length();
39 }
40 
41 void XMLObjectImplem::addAttribute(const std::string& name,
42  const std::string& value)
43 {
44  attributes_[name] = value;
45 }
46 
48 {
49  children_.append(child);
50 }
51 
52 void XMLObjectImplem::addContent(const std::string& contentLine)
53 {
54  content_.append(contentLine);
55 }
56 
58 {
60  // does bound checking within content_.erase if BoundaryChecks are enabled
61  content_.erase(pos);
62 }
63 
65 {
66  return children_[i];
67 }
68 
69 std::string XMLObjectImplem::header(bool strictXML) const
70 {
71  std::string rtn = "<" + tag_;
72  for (Map::const_iterator i=attributes_.begin(); i!=attributes_.end(); ++i)
73  {
74  if (strictXML)
75  {
76  rtn += " "
77  + (*i).first
78  + "="
79  + XMLifyAttVal((*i).second);
80  }
81  else
82  {
83  rtn += " " + (*i).first + "=\"" + (*i).second + "\"";
84  }
85  }
86 
87  rtn += ">";
88  return rtn;
89 }
90 
91 std::string XMLObjectImplem::XMLifyAttVal(const std::string &attval) {
92  std::string ret;
93  bool hasQuot, hasApos;
94  char delim;
95 
96  if (attval.find("\"") == std::string::npos)
97  {
98  hasQuot = false;
99  }
100  else
101  {
102  hasQuot = true;
103  }
104 
105  if (attval.find("\'") == std::string::npos)
106  {
107  hasApos = false;
108  }
109  else
110  {
111  hasApos = true;
112  }
113 
114  if (!hasQuot || hasApos)
115  {
116  delim = '\"'; // wrap the attribute value in "
117  }
118  else
119  {
120  delim = '\''; // wrap the attribute value in '
121  }
122 
123  // Rules:
124  // "-wrapped std::string cannot contain a literal "
125  // '-wrapped std::string cannot contain a literal '
126  // attribute value cannot contain a literal <
127  // attribute value cannot contain a literal &
128  ret.push_back(delim);
129  for (std::string::const_iterator i=attval.begin(); i != attval.end(); i++)
130  {
131  if (*i == delim)
132  {
133  if (delim == '\'') ret.append("&apos;");
134  else if (delim == '\"') ret.append("&quot;");
135  }
136  else if (*i == '&')
137  {
138  ret.append("&amp;");
139  }
140  else if (*i == '<')
141  {
142  ret.append("&lt;");
143  }
144  else
145  {
146  ret.push_back(*i);
147  }
148  }
149  ret.push_back(delim);
150 
151  return ret;
152 }
153 
154 std::string XMLObjectImplem::terminatedHeader(bool strictXML) const
155 {
156  std::string rtn = "<" + tag_;
157  for (Map::const_iterator i=attributes_.begin(); i!=attributes_.end(); ++i)
158  {
159  if (strictXML)
160  {
161  rtn += " "
162  + (*i).first
163  + "="
164  + XMLifyAttVal((*i).second);
165  }
166  else
167  {
168  rtn += " " + (*i).first + "=\"" + (*i).second + "\"";
169  }
170  }
171 
172  rtn += "/>";
173  return rtn;
174 }
175 
176 std::string XMLObjectImplem::toString() const
177 {
178  std::string rtn;
179  if (content_.length()==0 && children_.length()==0)
180  {
181  rtn = terminatedHeader(true) + "\n";
182  }
183  else
184  {
185  rtn = header() + "\n";
186  bool allBlankContent = true;
187  for (int i=0; i<content_.length(); i++)
188  {
189  if (!StrUtils::isWhite(content_[i]))
190  {
191  allBlankContent=false;
192  break;
193  }
194  }
195  if (!allBlankContent)
196  {
197  for (int i=0; i<content_.length(); i++)
198  {
199  rtn += content_[i];
200  }
201  rtn += "\n";
202  }
203  for (int i=0; i<children_.length(); i++)
204  {
205  rtn += children_[i].toString();
206  }
207  rtn += "</" + tag_ + ">\n";
208  }
209  return rtn;
210 }
211 
212 void XMLObjectImplem::print(std::ostream& os, int indent) const
213 {
214  for (int i=0; i<indent; i++) os << " ";
215  if (content_.length()==0 && children_.length()==0)
216  {
217  os << terminatedHeader(true) << std::endl;
218  return;
219  }
220  else
221  {
222  os << header(true) << std::endl;
223  printContent(os, indent+2);
224 
225  for (int i=0; i<children_.length(); i++)
226  {
227  children_[i].print(os, indent+2);
228  }
229  for (int i=0; i<indent; i++) os << " ";
230  os << "</" << tag_ << ">\n";
231  }
232 }
233 
234 void XMLObjectImplem::printContent(std::ostream& os, int indent) const
235 {
236  std::string space = "";
237  for (int i=0; i<indent; i++) space += " ";
238 
239  bool allBlankContent = true;
240  for (int i=0; i<content_.length(); i++)
241  {
242  if (!StrUtils::isWhite(content_[i]))
243  {
244  allBlankContent=false;
245  break;
246  }
247  }
248 
249  if (!allBlankContent)
250  {
251 
252  for (int i=0; i<content_.length(); i++)
253  {
254  // remove leading spaces, we will indent
255  std::string s(content_[i]);
256  s.erase(size_t(0), s.find_first_not_of(" \r\t"));
257  if((s.length()>0) && (!StrUtils::isWhite(s)))
258  os << space << s << '\n';
259  }
260  }
261 }
262 
std::string toString() const
Write as a std::string. Output may be ill-formed XML.
Array< T > & append(const T &x)
Add a new entry at the end of the array.
void printContent(std::ostream &os, int indent) const
Print content lines using the given indentation level.
void addChild(const XMLObject &child)
Add a child XMLObject.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
XMLObjectImplem * deepCopy() const
Deep copy.
const XMLObject & getChild(int i) const
Look up a child by its index.
iterator erase(iterator position)
A std::string utilities class for Teuchos.
Representation of an XML data tree. XMLObject is a ref-counted handle to a XMLObjectImplem object...
void addContent(const std::string &contentLine)
Add a content line.
std::string terminatedHeader(bool strictXML=false) const
Write the header terminated as &lt;Header&gt;
static bool isWhite(const std::string &str)
Returns true if a std::string consists entirely of whitespace.
XMLObjectImplem(const std::string &tag)
Construct with a &#39;tag&#39;.
void removeContentLine(const size_t &i)
Remove content line by index.
int length() const
Return number of elements in the array.
void print(std::ostream &os, int indent) const
Print to stream with the given indentation level. Output will be well-formed XML. ...
std::string header(bool strictXML=false) const
Write the header.
The XMLObjectImplem class takes care of the low-level implementation details of XMLObject.
void addAttribute(const std::string &name, const std::string &value)
Add a [name, value] attribute.
int numChildren() const
Return the number of children.
iterator begin()
static std::string XMLifyAttVal(const std::string &attval)
Convert attribute value text into well-formed XML.
An object representation of a subset of XML data.
Replacement for std::vector that is compatible with the Teuchos Memory Management classes...