Teuchos Package Browser (Single Doxygen Collection) Version of the Day
Teuchos_XMLObjectImplem.cpp
Go to the documentation of this file.
00001 // @HEADER
00002 // ***********************************************************************
00003 //
00004 //                    Teuchos: Common Tools Package
00005 //                 Copyright (2004) Sandia Corporation
00006 //
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00038 //
00039 // ***********************************************************************
00040 // @HEADER
00041 
00042 #include "Teuchos_XMLObject.hpp"
00043 #include "Teuchos_StrUtils.hpp"
00044 #include <cstring>
00045 
00046 using namespace Teuchos;
00047 
00048 
00049 XMLObjectImplem::XMLObjectImplem(const std::string& tag)
00050   : tag_(tag), attributes_(), children_(0), content_(0)
00051 {;}
00052 
00053 XMLObjectImplem* XMLObjectImplem::deepCopy() const 
00054 {
00055   XMLObjectImplem* rtn = new XMLObjectImplem(tag_);
00056   TEUCHOS_TEST_FOR_EXCEPTION(rtn==0, std::runtime_error, "XMLObjectImplem::deepCopy()");
00057   rtn->attributes_ = attributes_;
00058   rtn->content_ = content_;
00059   
00060   for (int i=0; i<children_.length(); i++)
00061   {
00062     rtn->addChild(children_[i].deepCopy());
00063   }
00064 
00065   return rtn;
00066 }
00067 
00068 int XMLObjectImplem::numChildren() const
00069 {
00070   return children_.length();
00071 }
00072 
00073 void XMLObjectImplem::addAttribute(const std::string& name,
00074            const std::string& value)
00075 {
00076   attributes_[name] = value;
00077 }
00078 
00079 void XMLObjectImplem::addChild(const XMLObject& child)
00080 {
00081   children_.append(child);
00082 }
00083 
00084 void XMLObjectImplem::addContent(const std::string& contentLine)
00085 {
00086   content_.append(contentLine);
00087 }
00088 
00089 void XMLObjectImplem::removeContentLine(const size_t& i)
00090 {
00091   Array<std::string>::iterator pos = content_.begin()+i;
00092   // does bound checking within content_.erase if BoundaryChecks are enabled
00093   content_.erase(pos);
00094 }
00095 
00096 const XMLObject& XMLObjectImplem::getChild(int i) const 
00097 {
00098   return children_[i];
00099 }
00100 
00101 std::string XMLObjectImplem::header(bool strictXML) const
00102 {
00103   std::string rtn = "<" + tag_;
00104   for (Map::const_iterator i=attributes_.begin(); i!=attributes_.end(); ++i)
00105   {
00106     if (strictXML)
00107     {
00108       rtn += " " 
00109   + (*i).first 
00110   + "="
00111   + XMLifyAttVal((*i).second);
00112     }
00113     else
00114     {
00115       rtn += " " + (*i).first + "=\"" + (*i).second + "\"";
00116     }
00117   }
00118   
00119   rtn += ">";
00120   return rtn;
00121 }
00122 
00123 std::string XMLObjectImplem::XMLifyAttVal(const std::string &attval) {
00124   std::string ret;
00125   bool hasQuot, hasApos;
00126   char delim;
00127 
00128   if (attval.find("\"") == std::string::npos)
00129   {
00130     hasQuot = false;
00131   }
00132   else
00133   {
00134     hasQuot = true;
00135   }
00136 
00137   if (attval.find("\'") == std::string::npos)
00138   {
00139     hasApos = false;
00140   }
00141   else
00142   {
00143     hasApos = true;
00144   }
00145 
00146   if (!hasQuot || hasApos)
00147   {
00148     delim = '\"'; // wrap the attribute value in "
00149   }
00150   else
00151   {
00152     delim = '\''; // wrap the attribute value in '
00153   }
00154 
00155   // Rules:
00156   // "-wrapped std::string cannot contain a literal "
00157   // '-wrapped std::string cannot contain a literal '
00158   // attribute value cannot contain a literal <
00159   // attribute value cannot contain a literal &
00160   ret.push_back(delim);
00161   for (std::string::const_iterator i=attval.begin(); i != attval.end(); i++)
00162   {
00163     if (*i == delim)
00164     {
00165       if (delim == '\'') ret.append("&apos;");
00166       else if (delim == '\"') ret.append("&quot;");
00167     }
00168     else if (*i == '&')
00169     {
00170       ret.append("&amp;");
00171     }
00172     else if (*i == '<')
00173     {
00174       ret.append("&lt;");
00175     }
00176     else
00177     {
00178       ret.push_back(*i);  
00179     }
00180   }
00181   ret.push_back(delim);
00182 
00183   return ret;
00184 }
00185 
00186 std::string XMLObjectImplem::terminatedHeader(bool strictXML) const
00187 {
00188   std::string rtn = "<" + tag_;
00189   for (Map::const_iterator i=attributes_.begin(); i!=attributes_.end(); ++i)
00190   {
00191     if (strictXML)
00192     {
00193       rtn += " " 
00194   + (*i).first 
00195   + "="
00196   + XMLifyAttVal((*i).second);
00197     }
00198     else
00199     {
00200       rtn += " " + (*i).first + "=\"" + (*i).second + "\"";
00201     }
00202   }
00203 
00204   rtn += "/>";
00205   return rtn;
00206 }
00207 
00208 std::string XMLObjectImplem::toString() const
00209 {
00210   std::string rtn;
00211   if (content_.length()==0 && children_.length()==0) 
00212   {
00213     rtn = terminatedHeader() + "\n";
00214   }
00215   else
00216   {
00217     rtn = header() + "\n";
00218     bool allBlankContent = true;
00219     for (int i=0; i<content_.length(); i++)
00220     {
00221       if (!StrUtils::isWhite(content_[i])) 
00222       {
00223   allBlankContent=false;
00224   break;
00225       }
00226     }
00227     if (!allBlankContent)
00228     {
00229       for (int i=0; i<content_.length(); i++)
00230       {
00231   rtn += content_[i];
00232       }
00233       rtn += "\n";
00234     }
00235     for (int i=0; i<children_.length(); i++)
00236     {
00237       rtn += children_[i].toString();
00238     }
00239     rtn += "</" + tag_ + ">\n";
00240   }
00241   return rtn;
00242 }
00243 
00244 void XMLObjectImplem::print(std::ostream& os, int indent) const
00245 {
00246   for (int i=0; i<indent; i++) os << " ";
00247   if (content_.length()==0 && children_.length()==0) 
00248   {
00249     os << terminatedHeader(true) << std::endl;
00250     return;
00251   }
00252   else
00253   {
00254     os << header(true) << std::endl;
00255     printContent(os, indent+2);
00256     
00257     for (int i=0; i<children_.length(); i++)
00258     {
00259       children_[i].print(os, indent+2);
00260     }
00261     for (int i=0; i<indent; i++) os << " ";
00262     os << "</" << tag_ << ">\n";
00263   }
00264 }
00265 
00266 void XMLObjectImplem::printContent(std::ostream& os, int indent) const 
00267 {
00268   std::string space = "";
00269   for (int i=0; i<indent; i++) space += " ";
00270 
00271   bool allBlankContent = true;
00272   for (int i=0; i<content_.length(); i++)
00273   {
00274     if (!StrUtils::isWhite(content_[i])) 
00275     {
00276       allBlankContent=false;
00277       break;
00278     }
00279   }
00280   
00281   if (!allBlankContent)
00282   {
00283 
00284     for (int i=0; i<content_.length(); i++)
00285     {
00286       // remove leading spaces, we will indent
00287       std::string s(content_[i]);
00288       s.erase(size_t(0), s.find_first_not_of(" \r\t"));
00289       if((s.length()>0) && (!StrUtils::isWhite(s)))
00290         os << space << s << '\n';
00291     }
00292   }
00293 }
00294 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines