XMLTextParser.cpp
Go to the documentation of this file.00001 //*** XMLTextParser.cpp *** 00002 00003 #include "XMLTextParser.h" 00004 #include "XMLAttributeList.h" 00005 #include "XMLObject.h" 00006 #include "XMLVariant.h" 00007 00008 #include "Debug.h" 00009 #include "Asset.h" 00010 00011 #include "irrXML/irrXML.h" 00012 using namespace irr; // irrXML is located in the namespace irr::io 00013 using namespace io; 00014 00015 00016 class FileReadCallBack_Asset: public IFileReadCallBack 00017 { 00018 public: 00019 FileReadCallBack_Asset(const Asset& asset) 00020 { 00021 asset_=&asset; 00022 bool result=asset_->Open(); 00023 // Report missing file 00024 #ifdef _DEBUG 00025 if (!result) 00026 { 00027 const char* filename=asset.GetFilename().GetString(); 00028 if (filename) 00029 { 00030 char errorMessage[1024]; 00031 SNPrintF(errorMessage,1024,"File not found: %s",filename); 00032 Assert(false,errorMessage); 00033 } 00034 else 00035 { 00036 Assert(false,"An asset could not be accessed."); 00037 } 00038 } 00039 #endif 00040 } 00041 00042 ~FileReadCallBack_Asset() 00043 { 00044 asset_->Close(); 00045 } 00046 00047 private: 00048 virtual int read(void* buffer, int sizeToRead) 00049 { 00050 return asset_->Read(static_cast<char*>(buffer), sizeToRead); 00051 } 00052 00053 virtual int getSize() 00054 { 00055 return asset_->GetSize(); 00056 } 00057 private: 00058 const Asset* asset_; 00059 }; 00060 00061 00062 //*** PushXMLObject *** 00063 00064 void XMLTextParser::PushXMLObject(XMLObject* object, StringId name) 00065 { 00066 // Create a new stack entry, and make it the topmost one 00067 XMLObjectStackEntry& entry=xmlObjects_.Add(XMLObjectStackEntry()); 00068 entry.object=object; 00069 entry.name=name; 00070 ; 00071 } 00072 00073 00074 //*** PopXMLObject *** 00075 00076 bool XMLTextParser::PopXMLObject() 00077 { 00078 // Check if we have any entries in the stack 00079 if (xmlObjects_.GetItemCount()>0) 00080 { 00081 xmlObjects_.RemoveLast(); 00082 return true; 00083 } 00084 else 00085 { 00086 return false; 00087 } 00088 } 00089 00090 00091 //*** TopXMLObject *** 00092 00093 XMLObject* XMLTextParser::TopXMLObject() 00094 { 00095 // Check if we have any entries in the stack 00096 if (xmlObjects_.GetItemCount()>0) 00097 { 00098 // Return the topmost object 00099 return xmlObjects_.Get(xmlObjects_.GetItemCount()-1).object; 00100 } 00101 else 00102 { 00103 // If stack is empty, return 0 00104 return 0; 00105 } 00106 } 00107 00108 00109 //*** TopName *** 00110 00111 StringId XMLTextParser::TopName() 00112 { 00113 // Check if we have any entries in the stack 00114 if (xmlObjects_.GetItemCount()>0) 00115 { 00116 // Return the topmost object 00117 return xmlObjects_.Get(xmlObjects_.GetItemCount()-1).name; 00118 } 00119 else 00120 { 00121 // If stack is empty, return 0 00122 return 0; 00123 } 00124 } 00125 00126 00127 //*** Parse *** 00128 00129 void XMLTextParser::Parse(const Asset& asset,XMLObject* xmlObject) 00130 { 00131 // Clear the stack 00132 xmlObjects_.Clear(); 00133 00134 // Push xmlObject on top of the stack 00135 PushXMLObject(xmlObject,""); 00136 00137 // create the reader using one of the factory functions 00138 FileReadCallBack_Asset xmlFileCallback(asset); 00139 IrrXMLReader* xml = createIrrXMLReader(&xmlFileCallback); 00140 bool firstElement=true; // We don't want an Element event sent to the top level object 00141 00142 // parse the file until end reached 00143 while(xml && xml->read()) 00144 { 00145 switch(xml->getNodeType()) 00146 { 00147 case EXN_ELEMENT: 00148 { 00149 // Read element name 00150 StringId elementName(xml->getNodeName()); 00151 00152 // Read all attributes 00153 XMLAttributeList attributes; 00154 for (int i=0; i<xml->getAttributeCount(); ++i) 00155 { 00156 attributes.Add(xml->getAttributeName(i),xml->getAttributeValue(i)); 00157 } 00158 00159 // If the topmost object of the stack is valid, it should receive an event 00160 if (TopXMLObject() && !firstElement) 00161 { 00162 XMLObject* newObject=TopXMLObject(); 00163 newObject=TopXMLObject()->XML_Element(elementName,attributes); 00164 // Push the received object onto the stack, regardless of whether it is valid or not (because it will be popped later) 00165 PushXMLObject(newObject,elementName); 00166 } 00167 firstElement=false; // The remaining elements should be sent 00168 00169 00170 // Send XML_Attribute events to the topmost object if it is valid 00171 if (TopXMLObject()) 00172 { 00173 // Loop through all attributes 00174 for (int i=0; i<attributes.GetCount(); ++i) 00175 { 00176 // Send XML_Attribute event 00177 TopXMLObject()->XML_Attribute(attributes.GetName(i),attributes.GetValue(i)); 00178 } 00179 } 00180 00181 00182 if (xml->isEmptyElement()) 00183 { 00184 // Cache the topmost object of the stack 00185 XMLObject* object=TopXMLObject(); 00186 00187 00188 // Send the XML_ElementEnd event to the topmost object, if it is valid 00189 if (object) 00190 { 00191 object->XML_ElementEnd(elementName); 00192 } 00193 00194 // Remove it from the stack 00195 PopXMLObject(); 00196 00197 // Get the parent object from the stack 00198 object=TopXMLObject(); 00199 00200 // Send the XML_ElementEnd event to the parent object, if it is valid 00201 if (object) 00202 { 00203 object->XML_ElementEnd(elementName); 00204 } 00205 } 00206 00207 } break; 00208 00209 case EXN_ELEMENT_END: 00210 { 00211 // Read element name 00212 StringId elementName(xml->getNodeName()); 00213 00214 // Cache the topmost object of the stack 00215 XMLObject* object=TopXMLObject(); 00216 00217 // Get buffered text 00218 DynamicBuffer* bufferedText=0; 00219 if (xmlObjects_.GetItemCount()>0) 00220 { 00221 bufferedText=&(xmlObjects_.Get(xmlObjects_.GetItemCount()-1).bufferedText); 00222 } 00223 00224 // Send Text event 00225 if (bufferedText && object && bufferedText->GetSize()>0) 00226 { 00227 char terminator='\0'; 00228 bufferedText->Write(&terminator); 00229 object->XML_Text(elementName,static_cast<const char*>(bufferedText->GetPointer())); 00230 bufferedText->Clear(false); 00231 } 00232 00233 00234 // Send the XML_ElementEnd event to the topmost object, if it is valid 00235 if (object) 00236 { 00237 object->XML_ElementEnd(elementName); 00238 } 00239 00240 // Remove it from the stack 00241 PopXMLObject(); 00242 00243 // Get the parent object from the stack 00244 object=TopXMLObject(); 00245 00246 // Send the XML_ElementEnd event to the parent object, if it is valid 00247 if (object) 00248 { 00249 object->XML_ElementEnd(elementName); 00250 } 00251 00252 } break; 00253 00254 00255 case EXN_TEXT: 00256 { 00257 const char* text=xml->getNodeData(); 00258 int length=StrLen(text); 00259 if (length<=0) 00260 { 00261 return; 00262 } 00263 00264 // Get buffered text 00265 DynamicBuffer* bufferedText=0; 00266 if (xmlObjects_.GetItemCount()>0) 00267 { 00268 bufferedText=&(xmlObjects_.Get(xmlObjects_.GetItemCount()-1).bufferedText); 00269 } 00270 00271 if (!bufferedText) 00272 { 00273 return; 00274 } 00275 00276 bufferedText->Write(text,length); 00277 } break; 00278 00279 case EXN_COMMENT: 00280 { 00281 } break; 00282 00283 case EXN_CDATA: 00284 { 00285 } break; 00286 } 00287 } 00288 00289 // delete the xml parser after usage 00290 delete xml; 00291 } 00292
Reproduction/republishing of any material on this site without permission is strictly prohibited.
