|
CLAM-Development
1.3
|
00001 /* 00002 * Copyright (c) 2001-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 _LibXmlDomReadingContext_hxx_ 00023 #define _LibXmlDomReadingContext_hxx_ 00024 00025 #include "Assert.hxx" 00026 #include "LibXmlEncodings.hxx" 00027 #include <libxml++/libxml++.h> 00028 #include <sstream> 00029 #include <list> 00030 #include <string> 00031 00032 namespace CLAM 00033 { 00034 class LibXmlDomDocumentHandler; 00035 00040 class LibXmlDomReadingContext 00041 { 00042 LibXmlDomReadingContext * _parentContext; 00043 xmlpp::Element * _context; 00044 xmlpp::Node::NodeList _children; 00045 xmlpp::Node::NodeList::iterator _currentChild; 00046 xmlpp::Element::AttributeList _attributes; 00047 std::stringstream _plainContentToParse; 00048 std::list<std::string> _errors; 00049 00050 public: 00051 LibXmlDomReadingContext(xmlpp::Element * element) 00052 { 00053 _parentContext=0; 00054 setAt(element); 00055 } 00056 00057 // TODO: Test this 00058 LibXmlDomReadingContext(LibXmlDomDocumentHandler & docHandler); 00059 00060 LibXmlDomReadingContext(LibXmlDomReadingContext * oldContext, const char * name) 00061 { 00062 _parentContext=oldContext; 00063 setAt(oldContext->fetchElement(name)); 00064 } 00065 void setAt(xmlpp::Element * element) 00066 { 00067 _context = element; 00068 _children = _context->get_children(); 00069 _attributes = _context->get_attributes(); 00070 _currentChild=_children.begin(); 00071 fetchContent(); 00072 } 00081 bool findElement(const char * name) 00082 { 00083 if (contentLeft()) return false; 00084 if (_currentChild==_children.end()) return false; // No nodes left 00085 xmlpp::Element * child = dynamic_cast<xmlpp::Element*>(*_currentChild); 00086 CLAM_ASSERT(child, 00087 "Can't change the context to a non element node"); 00088 if (child->get_name()!=U(name)) return false; // Name mismatch 00089 return true; 00090 } 00098 xmlpp::Element * fetchElement(const char * name) 00099 { 00100 bool hasContentLeft = contentLeft(); 00101 CLAM_ASSERT(!hasContentLeft, "Fetching element with content left"); 00102 CLAM_ASSERT(_currentChild!=_children.end(), 00103 "Accessing beyond DOM nodes"); 00104 xmlpp::Element * child = dynamic_cast<xmlpp::Element *>(*_currentChild); 00105 CLAM_ASSERT(child, 00106 "Can't change the context to a non element node"); 00107 CLAM_ASSERT(L(child->get_name())==name, 00108 "XML element name should be the one expected"); 00109 _currentChild++; 00110 fetchContent(); 00111 return child; 00112 } 00113 00114 LibXmlDomReadingContext * release() 00115 { 00116 checkNoContentLeftOrError(); 00117 checkNoElementLeftOrError(); 00118 return _parentContext; 00119 } 00120 00121 void checkNoContentLeftOrError() 00122 { 00123 if (!contentLeft()) return; 00124 std::ostringstream os; 00125 os << "Unexpected content: '"; 00126 for (int c=_plainContentToParse.get(); not _plainContentToParse.eof(); c=_plainContentToParse.get()) 00127 os.put(c); 00128 os << "' at position "; 00129 os << getPath(); 00130 _errors.push_back(os.str()); 00131 } 00132 void checkNoElementLeftOrError() 00133 { 00134 if (_currentChild==_children.end()) return; 00135 xmlpp::Element * child = dynamic_cast<xmlpp::Element*>(*_currentChild); 00136 /* 00137 if (!child) 00138 _errors.push_back("Unexpected node type"); 00139 */ 00140 00141 std::ostringstream os; 00142 os << "Unexpected Element: '"; 00143 os << L(child->get_name()); 00144 os << "' at position "; 00145 os << getPath(); 00146 00147 _errors.push_back(os.str()); 00148 } 00149 00150 bool extractAttribute(const char * attributeName, std::ostream & os) 00151 { 00152 xmlpp::Attribute * attribute = 00153 _context->get_attribute(U(attributeName)); 00154 if (!attribute) return false; 00155 os << L(attribute->get_value()) << std::flush; 00156 return true; 00157 } 00158 00159 std::istream & reachableContent() 00160 { 00161 return _plainContentToParse; 00162 } 00168 void fetchContent() 00169 { 00170 // _plainContentToParse.clear(); // Clear any error flag 00171 for (; _currentChild!=_children.end(); _currentChild++) 00172 { 00173 xmlpp::Node * child= *_currentChild; 00174 if (dynamic_cast<xmlpp::CommentNode*>(child)) continue; 00175 xmlpp::TextNode * textNode = dynamic_cast<xmlpp::TextNode*>(child); 00176 if (!textNode) break; 00177 _plainContentToParse << L(textNode->get_content()); 00178 } 00179 _plainContentToParse << std::flush; 00180 contentLeft(); 00181 } 00182 00187 bool contentLeft() 00188 { 00189 int c = _plainContentToParse.peek(); 00190 while (not _plainContentToParse.eof()) 00191 { 00192 if (!isspace(c)) return true; 00193 _plainContentToParse.ignore(); 00194 c = _plainContentToParse.peek(); 00195 } 00196 _plainContentToParse.clear(); 00197 return false; 00198 } 00199 std::list<std::string> errors() 00200 { 00201 return _errors; 00202 } 00203 00204 std::string getPath() 00205 { 00206 return L(_context->get_path()); 00207 // TODO: Remove the by hand way 00208 std::string path; 00209 if (_parentContext) path=_parentContext->getPath(); 00210 path += '/'; 00211 path += L(_context->get_name()); 00212 return path; 00213 } 00214 }; 00215 00216 } // Namespace CLAM 00217 00218 #endif//_LibXmlDomReadingContext_hxx_ 00219 00220 00221
1.7.6.1