CLAM-Development
1.1
|
00001 /* 00002 * Copyright (c) 2004 MUSIC TECHNOLOGY GROUP (MTG) 00003 * UNIVERSITAT POMPEU FABRA 00004 * 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00019 * 00020 */ 00021 00022 #ifndef __XMLWRITECONTEXT_HXX__ 00023 #define __XMLWRITECONTEXT_HXX__ 00024 00025 #include <ostream> 00026 #include <string> 00027 #include "Assert.hxx" 00028 00029 namespace CLAM 00030 { 00043 class XmlWriteContext 00044 { 00045 public: 00046 XmlWriteContext(std::ostream & targetStream) : 00047 mTarget(targetStream) 00048 { 00049 CLAM_ASSERT(!sCurrentContext, 00050 "An XML generation context is already defined"); 00051 sCurrentContext = this; 00052 mLastWasAContent=false; 00053 mElementInserted=false; 00054 mTagOpened=false; 00055 mCurrentLevel = 0; 00056 mUseIndentation=false; 00057 } 00058 00059 ~XmlWriteContext() 00060 { 00061 sCurrentContext = 0; 00062 } 00063 00064 static XmlWriteContext & CurrentContext() 00065 { 00066 CLAM_ASSERT(sCurrentContext,"XML generation context not created"); 00067 return *sCurrentContext; 00068 } 00069 00070 std::ostream & GetTarget() 00071 { 00072 return mTarget; 00073 } 00074 00075 template <typename T> 00076 void InsertContent(const T & content) 00077 { 00078 if (mTagOpened) EndOpenTag(); 00079 if (mElementInserted) 00080 NewIndentedLineIfEnabled(); 00081 mTarget << content; 00082 mLastWasAContent = true; 00083 } 00084 00085 void OpenElement(const std::string & name) 00086 { 00087 if (mTagOpened) EndOpenTag(); 00088 NewIndentedLineIfEnabled(); 00089 // TODO: Change the temporary to normal insertion with the upgrade to 0.5.2 00090 mTarget << std::string("<") << name; 00091 mTagOpened = true; 00092 mElementInserted = false; 00093 mLastWasAContent = false; 00094 mCurrentLevel++; 00095 } 00096 00097 void CloseElement(const std::string & name) 00098 { 00099 mCurrentLevel--; 00100 if (mLastWasAContent || mElementInserted) 00101 CloseFullElement(name); 00102 else 00103 CloseEmptyElement(); 00104 mElementInserted = true; 00105 mLastWasAContent = false; 00106 } 00107 00108 template <typename T> 00109 void InsertAttribute(const std::string &name, const T & content) 00110 { 00111 CLAM_ASSERT(mTagOpened, "Appending attribute outside a tag"); 00112 mTarget << std::string(" ") << name << std::string("='") 00113 << content << std::string("'"); 00114 } 00115 00120 bool LastWasAContent() 00121 { 00122 return mLastWasAContent; 00123 } 00124 00128 bool ElementInserted() 00129 { 00130 return mElementInserted; 00131 } 00132 00133 unsigned int CurrentLevel() 00134 { 00135 return mCurrentLevel; 00136 } 00137 00138 void UseIndentation(bool useIt) 00139 { 00140 mUseIndentation = useIt; 00141 } 00142 00143 private: 00144 00145 void CloseFullElement(const std::string & name) 00146 { 00147 if (mElementInserted) 00148 NewIndentedLineIfEnabled(); 00149 // TODO: Change the temporary to normal insertion with the upgrade to 0.5.2 00150 mTarget << std::string("</") << name << std::string(">"); 00151 } 00152 00153 void CloseEmptyElement() 00154 { 00155 CLAM_ASSERT(mTagOpened,"No open tag to close"); 00156 // TODO: Change the temporary to normal insertion with the upgrade to 0.5.2 00157 mTarget << std::string(" />"); 00158 mTagOpened = false; 00159 } 00160 00161 void EndOpenTag() 00162 { 00163 CLAM_ASSERT(mTagOpened,"No open tag to close"); 00164 // TODO: Change the temporary to normal insertion with the upgrade to 0.5.2 00165 mTarget << std::string(">"); 00166 mTagOpened = false; 00167 } 00168 00169 void NewIndentedLineIfEnabled() 00170 { 00171 if (!mUseIndentation) return; 00172 // TODO: Change the temporary to normal insertion with the upgrade to 0.5.2 00173 if (mCurrentLevel!=0 || mLastWasAContent || mElementInserted) 00174 mTarget << std::string("\n"); 00175 mTarget << std::string(mCurrentLevel,'\t'); 00176 } 00177 00178 private: 00179 00180 std::ostream & mTarget; 00181 bool mLastWasAContent; 00182 bool mElementInserted; 00183 bool mTagOpened; 00184 bool mUseIndentation; 00185 unsigned int mCurrentLevel; 00186 00187 static XmlWriteContext * sCurrentContext; 00188 00189 }; 00190 00191 } // ns CLAM 00192 00193 #endif//__XMLWRITECONTEXT_HXX__ 00194