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 //
4 // Teuchos: Common Tools Package
5 // Copyright (2004) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38 //
39 // ***********************************************************************
40 // @HEADER
41 
42 #include "Teuchos_XMLObject.hpp"
43 #include "Teuchos_StrUtils.hpp"
44 #include <cstring>
45 
46 using namespace Teuchos;
47 
48 
49 XMLObjectImplem::XMLObjectImplem(const std::string& tag)
50  : tag_(tag), attributes_(), children_(0), content_(0)
51 {;}
52 
54 {
56  TEUCHOS_TEST_FOR_EXCEPTION(rtn==0, std::runtime_error, "XMLObjectImplem::deepCopy()");
57  rtn->attributes_ = attributes_;
58  rtn->content_ = content_;
59 
60  for (int i=0; i<children_.length(); i++)
61  {
62  rtn->addChild(children_[i].deepCopy());
63  }
64 
65  return rtn;
66 }
67 
69 {
70  return children_.length();
71 }
72 
73 void XMLObjectImplem::addAttribute(const std::string& name,
74  const std::string& value)
75 {
76  attributes_[name] = value;
77 }
78 
80 {
81  children_.append(child);
82 }
83 
84 void XMLObjectImplem::addContent(const std::string& contentLine)
85 {
86  content_.append(contentLine);
87 }
88 
90 {
92  // does bound checking within content_.erase if BoundaryChecks are enabled
93  content_.erase(pos);
94 }
95 
97 {
98  return children_[i];
99 }
100 
101 std::string XMLObjectImplem::header(bool strictXML) const
102 {
103  std::string rtn = "<" + tag_;
104  for (Map::const_iterator i=attributes_.begin(); i!=attributes_.end(); ++i)
105  {
106  if (strictXML)
107  {
108  rtn += " "
109  + (*i).first
110  + "="
111  + XMLifyAttVal((*i).second);
112  }
113  else
114  {
115  rtn += " " + (*i).first + "=\"" + (*i).second + "\"";
116  }
117  }
118 
119  rtn += ">";
120  return rtn;
121 }
122 
123 std::string XMLObjectImplem::XMLifyAttVal(const std::string &attval) {
124  std::string ret;
125  bool hasQuot, hasApos;
126  char delim;
127 
128  if (attval.find("\"") == std::string::npos)
129  {
130  hasQuot = false;
131  }
132  else
133  {
134  hasQuot = true;
135  }
136 
137  if (attval.find("\'") == std::string::npos)
138  {
139  hasApos = false;
140  }
141  else
142  {
143  hasApos = true;
144  }
145 
146  if (!hasQuot || hasApos)
147  {
148  delim = '\"'; // wrap the attribute value in "
149  }
150  else
151  {
152  delim = '\''; // wrap the attribute value in '
153  }
154 
155  // Rules:
156  // "-wrapped std::string cannot contain a literal "
157  // '-wrapped std::string cannot contain a literal '
158  // attribute value cannot contain a literal <
159  // attribute value cannot contain a literal &
160  ret.push_back(delim);
161  for (std::string::const_iterator i=attval.begin(); i != attval.end(); i++)
162  {
163  if (*i == delim)
164  {
165  if (delim == '\'') ret.append("&apos;");
166  else if (delim == '\"') ret.append("&quot;");
167  }
168  else if (*i == '&')
169  {
170  ret.append("&amp;");
171  }
172  else if (*i == '<')
173  {
174  ret.append("&lt;");
175  }
176  else
177  {
178  ret.push_back(*i);
179  }
180  }
181  ret.push_back(delim);
182 
183  return ret;
184 }
185 
186 std::string XMLObjectImplem::terminatedHeader(bool strictXML) const
187 {
188  std::string rtn = "<" + tag_;
189  for (Map::const_iterator i=attributes_.begin(); i!=attributes_.end(); ++i)
190  {
191  if (strictXML)
192  {
193  rtn += " "
194  + (*i).first
195  + "="
196  + XMLifyAttVal((*i).second);
197  }
198  else
199  {
200  rtn += " " + (*i).first + "=\"" + (*i).second + "\"";
201  }
202  }
203 
204  rtn += "/>";
205  return rtn;
206 }
207 
208 std::string XMLObjectImplem::toString() const
209 {
210  std::string rtn;
211  if (content_.length()==0 && children_.length()==0)
212  {
213  rtn = terminatedHeader(true) + "\n";
214  }
215  else
216  {
217  rtn = header() + "\n";
218  bool allBlankContent = true;
219  for (int i=0; i<content_.length(); i++)
220  {
221  if (!StrUtils::isWhite(content_[i]))
222  {
223  allBlankContent=false;
224  break;
225  }
226  }
227  if (!allBlankContent)
228  {
229  for (int i=0; i<content_.length(); i++)
230  {
231  rtn += content_[i];
232  }
233  rtn += "\n";
234  }
235  for (int i=0; i<children_.length(); i++)
236  {
237  rtn += children_[i].toString();
238  }
239  rtn += "</" + tag_ + ">\n";
240  }
241  return rtn;
242 }
243 
244 void XMLObjectImplem::print(std::ostream& os, int indent) const
245 {
246  for (int i=0; i<indent; i++) os << " ";
247  if (content_.length()==0 && children_.length()==0)
248  {
249  os << terminatedHeader(true) << std::endl;
250  return;
251  }
252  else
253  {
254  os << header(true) << std::endl;
255  printContent(os, indent+2);
256 
257  for (int i=0; i<children_.length(); i++)
258  {
259  children_[i].print(os, indent+2);
260  }
261  for (int i=0; i<indent; i++) os << " ";
262  os << "</" << tag_ << ">\n";
263  }
264 }
265 
266 void XMLObjectImplem::printContent(std::ostream& os, int indent) const
267 {
268  std::string space = "";
269  for (int i=0; i<indent; i++) space += " ";
270 
271  bool allBlankContent = true;
272  for (int i=0; i<content_.length(); i++)
273  {
274  if (!StrUtils::isWhite(content_[i]))
275  {
276  allBlankContent=false;
277  break;
278  }
279  }
280 
281  if (!allBlankContent)
282  {
283 
284  for (int i=0; i<content_.length(); i++)
285  {
286  // remove leading spaces, we will indent
287  std::string s(content_[i]);
288  s.erase(size_t(0), s.find_first_not_of(" \r\t"));
289  if((s.length()>0) && (!StrUtils::isWhite(s)))
290  os << space << s << '\n';
291  }
292  }
293 }
294 
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...