00001 /* 00002 * Copyright (C) 2003-2009 Olivier Boudeville 00003 * 00004 * This file is part of the Ceylan library. 00005 * 00006 * The Ceylan library is free software: you can redistribute it and/or modify 00007 * it under the terms of either the GNU Lesser General Public License or 00008 * the GNU General Public License, as they are published by the Free Software 00009 * Foundation, either version 3 of these Licenses, or (at your option) 00010 * any later version. 00011 * 00012 * The Ceylan library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU Lesser General Public License and the GNU General Public License 00016 * for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License and the GNU General Public License along with the Ceylan library. 00020 * If not, see <http://www.gnu.org/licenses/>. 00021 * 00022 * Author: Olivier Boudeville (olivier.boudeville@esperide.com) 00023 * 00024 */ 00025 00026 00027 #include "CeylanXMLVisitor.h" 00028 00029 #include "CeylanOutputStream.h" // for OutputStream 00030 #include "CeylanXML.h" // for LowerThan, etc. 00031 #include "CeylanXMLElement.h" // for XLMMarkup, etc. 00032 #include "CeylanOperators.h" // for toString 00033 #include "CeylanLogPlug.h" // for LogPlug 00034 00035 00036 00037 using namespace Ceylan ; 00038 using namespace Ceylan::System ; 00039 using namespace Ceylan::XML ; 00040 00041 using std::string ; 00042 using std::list ; 00043 00044 00045 00046 00047 00048 XMLVisitorException::XMLVisitorException( const std::string & reason ) : 00049 XMLException( reason ) 00050 { 00051 00052 } 00053 00054 00055 00056 XMLVisitorException::~XMLVisitorException() throw() 00057 { 00058 00059 } 00060 00061 00062 00063 00064 00065 00066 // XMLVisitor section. 00067 00068 00069 00070 00071 XMLVisitor::XMLVisitor() 00072 { 00073 00074 } 00075 00076 00077 XMLVisitor::~XMLVisitor() throw() 00078 { 00079 00080 } 00081 00082 00083 const string XMLVisitor::toString( Ceylan::VerbosityLevels level ) const 00084 { 00085 00086 return "XML visitor" ; 00087 00088 } 00089 00090 00091 00092 00093 00094 // XMLSavingVisitor section. 00095 00096 00097 string XMLSavingVisitor::OffsetForMarkup = "\t" ; 00098 00099 00100 00101 XMLSavingVisitor::XMLSavingVisitor( System::OutputStream & output ) : 00102 _output( &output ) 00103 { 00104 00105 } 00106 00107 00108 00109 XMLSavingVisitor::~XMLSavingVisitor() throw() 00110 { 00111 00112 // _output stream not owned. 00113 00114 } 00115 00116 00117 00118 void XMLSavingVisitor::incrementHeight() 00119 { 00120 00121 //Log::LogPlug::trace( "XMLSavingVisitor::incrementHeight" ) ; 00122 00123 /* 00124 * Does nothing, as the information is already stored in the markup stack, 00125 * when the visit of an enclosing element occurred. 00126 * 00127 */ 00128 00129 } 00130 00131 00132 00133 Ceylan::Height XMLSavingVisitor::getHeight() const 00134 { 00135 00136 return static_cast<Ceylan::Height>( _markupsToClose.size() ) ; 00137 00138 } 00139 00140 00141 00142 void XMLSavingVisitor::decrementHeight() 00143 { 00144 00145 //Log::LogPlug::trace( "XMLSavingVisitor::decrementHeight" ) ; 00146 00147 ClosingMarkup popped = _markupsToClose.top() ; 00148 _markupsToClose.pop() ; 00149 00150 if ( popped.empty() ) 00151 return ; 00152 00153 Height offset = getHeight() ; 00154 00155 for ( Size s = 0; s < offset; s++ ) 00156 _output->write( OffsetForMarkup ) ; 00157 00158 _output->write( popped + EndOfLine ) ; 00159 00160 } 00161 00162 00163 00164 void XMLSavingVisitor::visit( XMLMarkup & xmlMarkup ) 00165 { 00166 00167 /* 00168 Log::LogPlug::trace( "XMLSavingVisitor::visiting markup " 00169 + xmlMarkup.toString() ) ; 00170 */ 00171 00172 Height offset = getHeight() ; 00173 00174 _markupsToClose.push( xmlMarkup.getClosingMarkup() ) ; 00175 00176 00177 for ( Size s = 0; s < offset; s++ ) 00178 _output->write( OffsetForMarkup ) ; 00179 00180 xmlMarkup.saveTo( *_output ) ; 00181 00182 _output->writeUint8( EndOfLine ) ; 00183 00184 } 00185 00186 00187 00188 void XMLSavingVisitor::visit( XMLText & xmlText ) 00189 { 00190 00191 /* 00192 Log::LogPlug::trace( "XMLSavingVisitor::visiting text " 00193 + xmlText.toString() ) ; 00194 */ 00195 00196 Height offset = getHeight() ; 00197 00198 _markupsToClose.push( "" ) ; 00199 00200 00201 for ( Size s = 0; s < offset; s++ ) 00202 _output->write( OffsetForMarkup ) ; 00203 00204 xmlText.saveTo( *_output ) ; 00205 00206 _output->writeUint8( EndOfLine ) ; 00207 00208 } 00209 00210 00211 00212 const string XMLSavingVisitor::toString( Ceylan::VerbosityLevels level ) const 00213 { 00214 00215 string res = "XML saving visitor, " ; 00216 00217 if ( _output != 0 ) 00218 res += "using as output stream " + _output->toString( level ) ; 00219 else 00220 res += " with no specific output stream registered" ; 00221 00222 if ( level == Ceylan::low ) 00223 return res ; 00224 00225 res += ". Markup stack " ; 00226 00227 if ( _markupsToClose.empty() ) 00228 { 00229 res += "is empty" ; 00230 } 00231 else 00232 { 00233 res += "has " + Ceylan::toString( 00234 static_cast<Ceylan::Uint32>( _markupsToClose.size() ) ) 00235 + " element(s)" ; 00236 } 00237 00238 return res ; 00239 00240 } 00241 00242 00243 00244 00245 00246 // XMLSearchingVisitor section. 00247 00248 00249 XMLSearchingVisitor::XMLSearchingVisitor( MarkupName & searchedMarkup ) : 00250 _searchedMarkup( searchedMarkup ) 00251 { 00252 00253 } 00254 00255 00256 00257 XMLSearchingVisitor::~XMLSearchingVisitor() throw() 00258 { 00259 00260 // Nothing owned. 00261 00262 } 00263 00264 00265 00266 list<XMLMarkup *> & XMLSearchingVisitor::getMatchingMarkups() 00267 { 00268 00269 return _matchingNodes ; 00270 00271 } 00272 00273 00274 00275 void XMLSearchingVisitor::visit( XMLMarkup & xmlMarkup ) 00276 { 00277 00278 if ( xmlMarkup.getMarkupName() == _searchedMarkup ) 00279 _matchingNodes.push_back( &xmlMarkup ) ; 00280 00281 } 00282 00283 00284 00285 void XMLSearchingVisitor::visit( XMLText & xmlText ) 00286 { 00287 00288 // Nothing to do for texts. 00289 00290 } 00291 00292 00293 00294 const string XMLSearchingVisitor::toString( Ceylan::VerbosityLevels level ) 00295 const 00296 { 00297 00298 return "XMLSearchingVisitor" ; 00299 00300 } 00301