Teuchos - Trilinos Tools Package Version of the Day
Teuchos_XMLObjectImplem.cpp
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 
00045 using namespace Teuchos;
00046 
00047 
00048 XMLObjectImplem::XMLObjectImplem(const std::string& tag)
00049   : tag_(tag), attributes_(), children_(0), content_(0)
00050 {;}
00051 
00052 XMLObjectImplem* XMLObjectImplem::deepCopy() const 
00053 {
00054   XMLObjectImplem* rtn = new XMLObjectImplem(tag_);
00055   TEUCHOS_TEST_FOR_EXCEPTION(rtn==0, std::runtime_error, "XMLObjectImplem::deepCopy()");
00056   rtn->attributes_ = attributes_;
00057   rtn->content_ = content_;
00058   
00059   for (int i=0; i<children_.length(); i++)
00060   {
00061     rtn->addChild(children_[i].deepCopy());
00062   }
00063 
00064   return rtn;
00065 }
00066 
00067 int XMLObjectImplem::numChildren() const
00068 {
00069   return children_.length();
00070 }
00071 
00072 void XMLObjectImplem::addAttribute(const std::string& name,
00073            const std::string& value)
00074 {
00075   attributes_[name] = value;
00076 }
00077 
00078 void XMLObjectImplem::addChild(const XMLObject& child)
00079 {
00080   children_.append(child);
00081 }
00082 
00083 void XMLObjectImplem::addContent(const std::string& contentLine)
00084 {
00085   content_.append(contentLine);
00086 }
00087 
00088 const XMLObject& XMLObjectImplem::getChild(int i) const 
00089 {
00090   return children_[i];
00091 }
00092 
00093 std::string XMLObjectImplem::header(bool strictXML) const
00094 {
00095   std::string rtn = "<" + tag_;
00096   for (Map::const_iterator i=attributes_.begin(); i!=attributes_.end(); ++i)
00097   {
00098     if (strictXML)
00099     {
00100       rtn += " " 
00101   + (*i).first 
00102   + "="
00103   + XMLifyAttVal((*i).second);
00104     }
00105     else
00106     {
00107       rtn += " " + (*i).first + "=\"" + (*i).second + "\"";
00108     }
00109   }
00110   
00111   rtn += ">";
00112   return rtn;
00113 }
00114 
00115 std::string XMLObjectImplem::XMLifyAttVal(const std::string &attval) {
00116   std::string ret;
00117   bool hasQuot, hasApos;
00118   char delim;
00119 
00120   if (attval.find("\"") == std::string::npos)
00121   {
00122     hasQuot = false;
00123   }
00124   else
00125   {
00126     hasQuot = true;
00127   }
00128 
00129   if (attval.find("\'") == std::string::npos)
00130   {
00131     hasApos = false;
00132   }
00133   else
00134   {
00135     hasApos = true;
00136   }
00137 
00138   if (!hasQuot || hasApos)
00139   {
00140     delim = '\"'; // wrap the attribute value in "
00141   }
00142   else
00143   {
00144     delim = '\''; // wrap the attribute value in '
00145   }
00146 
00147   // Rules:
00148   // "-wrapped std::string cannot contain a literal "
00149   // '-wrapped std::string cannot contain a literal '
00150   // attribute value cannot contain a literal <
00151   // attribute value cannot contain a literal &
00152   ret.push_back(delim);
00153   for (std::string::const_iterator i=attval.begin(); i != attval.end(); i++)
00154   {
00155     if (*i == delim)
00156     {
00157       if (delim == '\'') ret.append("&apos;");
00158       else if (delim == '\"') ret.append("&quot;");
00159     }
00160     else if (*i == '&')
00161     {
00162       ret.append("&amp;");
00163     }
00164     else if (*i == '<')
00165     {
00166       ret.append("&lt;");
00167     }
00168     else
00169     {
00170       ret.push_back(*i);  
00171     }
00172   }
00173   ret.push_back(delim);
00174 
00175   return ret;
00176 }
00177 
00178 std::string XMLObjectImplem::terminatedHeader(bool strictXML) const
00179 {
00180   std::string rtn = "<" + tag_;
00181   for (Map::const_iterator i=attributes_.begin(); i!=attributes_.end(); ++i)
00182   {
00183     if (strictXML)
00184     {
00185       rtn += " " 
00186   + (*i).first 
00187   + "="
00188   + XMLifyAttVal((*i).second);
00189     }
00190     else
00191     {
00192       rtn += " " + (*i).first + "=\"" + (*i).second + "\"";
00193     }
00194   }
00195 
00196   rtn += "/>";
00197   return rtn;
00198 }
00199 
00200 std::string XMLObjectImplem::toString() const
00201 {
00202   std::string rtn;
00203   if (content_.length()==0 && children_.length()==0) 
00204   {
00205     rtn = terminatedHeader() + "\n";
00206   }
00207   else
00208   {
00209     rtn = header() + "\n";
00210     bool allBlankContent = true;
00211     for (int i=0; i<content_.length(); i++)
00212     {
00213       if (!StrUtils::isWhite(content_[i])) 
00214       {
00215   allBlankContent=false;
00216   break;
00217       }
00218     }
00219     if (!allBlankContent)
00220     {
00221       for (int i=0; i<content_.length(); i++)
00222       {
00223   rtn += content_[i];
00224       }
00225       rtn += "\n";
00226     }
00227     for (int i=0; i<children_.length(); i++)
00228     {
00229       rtn += children_[i].toString();
00230     }
00231     rtn += "</" + tag_ + ">\n";
00232   }
00233   return rtn;
00234 }
00235 
00236 void XMLObjectImplem::print(std::ostream& os, int indent) const
00237 {
00238   for (int i=0; i<indent; i++) os << " ";
00239   if (content_.length()==0 && children_.length()==0) 
00240   {
00241     os << terminatedHeader(true) << std::endl;
00242     return;
00243   }
00244   else
00245   {
00246     os << header(true) << std::endl;
00247     printContent(os, indent+2);
00248     
00249     for (int i=0; i<children_.length(); i++)
00250     {
00251       children_[i].print(os, indent+2);
00252     }
00253     for (int i=0; i<indent; i++) os << " ";
00254     os << "</" << tag_ << ">\n";
00255   }
00256 }
00257 
00258 void XMLObjectImplem::printContent(std::ostream& os, int indent) const 
00259 {
00260   std::string space = "";
00261   for (int i=0; i<indent; i++) space += " ";
00262 
00263   bool allBlankContent = true;
00264   for (int i=0; i<content_.length(); i++)
00265   {
00266     if (!StrUtils::isWhite(content_[i])) 
00267     {
00268       allBlankContent=false;
00269       break;
00270     }
00271   }
00272   
00273   if (!allBlankContent) 
00274   {
00275     os << space;
00276     for (int i=0; i<content_.length(); i++)
00277     {
00278       os << content_[i];
00279     }
00280     os << '\n';
00281   }
00282 }
00283 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines