|
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 _XercesDomReadingContext_hxx_ 00023 #define _XercesDomReadingContext_hxx_ 00024 00025 #include "Assert.hxx" 00026 #include "XercesEncodings.hxx" 00027 #include <xercesc/dom/DOMElement.hpp> 00028 #include <xercesc/dom/DOMNamedNodeMap.hpp> 00029 #include <xercesc/dom/DOMNodeList.hpp> 00030 #include <sstream> 00031 #include <list> 00032 #include <string> 00033 00034 namespace CLAM 00035 { 00036 class XercesDomDocumentHandler; 00037 00042 class XercesDomReadingContext 00043 { 00044 xercesc::DOMElement * _context; 00045 xercesc::DOMNodeList * _children; 00046 xercesc::DOMNamedNodeMap * _attributes; 00047 std::stringstream _plainContentToParse; 00048 unsigned int _currentChild; 00049 XercesDomReadingContext * _parentContext; 00050 std::list<std::string> _errors; 00051 00052 // std::list<std::string> & _currentPath; 00053 public: 00054 XercesDomReadingContext(xercesc::DOMElement * element) 00055 { 00056 _parentContext=0; 00057 setAt(element); 00058 } 00059 // TODO: Test this 00060 XercesDomReadingContext(XercesDomDocumentHandler & docHandler); 00061 00062 XercesDomReadingContext(XercesDomReadingContext * oldContext, const char * name) 00063 { 00064 _parentContext=oldContext; 00065 setAt(oldContext->fetchElement(name)); 00066 } 00067 void setAt(xercesc::DOMElement * element) 00068 { 00069 _context = element; 00070 _children = _context->getChildNodes(); 00071 _attributes = _context->getAttributes(); 00072 _currentChild=0; 00073 fetchContent(); 00074 } 00075 00084 bool findElement(const char * name) 00085 { 00086 if (contentLeft()) return false; 00087 if (_currentChild==_children->getLength()) return false; // No nodes left 00088 00089 xercesc::DOMNode * child = _children->item(_currentChild); 00090 CLAM_ASSERT(child->getNodeType() == xercesc::DOMNode::ELEMENT_NODE, 00091 "Can't change the context to a non element node"); 00092 if (!xercesc::XMLString::equals(child->getNodeName(), U(name))) return false; // Name mismatch 00093 return true; 00094 } 00095 00103 xercesc::DOMElement * fetchElement(const char * name) 00104 { 00105 bool hasContentLeft; 00106 hasContentLeft = contentLeft(); 00107 CLAM_ASSERT(!hasContentLeft, "Fetching element with content left"); 00108 CLAM_ASSERT(_currentChild!=_children->getLength(), 00109 "Accessing beyond DOM nodes"); 00110 xercesc::DOMNode * child = _children->item(_currentChild); 00111 CLAM_ASSERT(child->getNodeType() == xercesc::DOMNode::ELEMENT_NODE, 00112 "Can't change the context to a non element node"); 00113 CLAM_ASSERT(xercesc::XMLString::equals(child->getNodeName(), U(name)), 00114 "XML element name should be the one expected"); 00115 _currentChild++; 00116 fetchContent(); 00117 return dynamic_cast<xercesc::DOMElement *>(child); 00118 } 00119 00120 XercesDomReadingContext * release() 00121 { 00122 checkNoContentLeftOrError(); 00123 checkNoElementLeftOrError(); 00124 return _parentContext; 00125 } 00126 00127 void checkNoContentLeftOrError() 00128 { 00129 if (!contentLeft()) return; 00130 std::ostringstream os; 00131 os << "Unexpected content: '"; 00132 for (int c=_plainContentToParse.get(); not _plainContentToParse.eof(); c=_plainContentToParse.get()) 00133 os.put(c); 00134 os << "' at position "; 00135 os << getPath(); 00136 _errors.push_back(os.str()); 00137 } 00138 00139 void checkNoElementLeftOrError() 00140 { 00141 if (_currentChild>=_children->getLength()) return; 00142 xercesc::DOMNode * child = _children->item(_currentChild); 00143 /* 00144 if (child->getNodeType() != xercesc::DOMNode::ELEMENT_NODE) 00145 { 00146 _errors.push_back("Unexpected node type"); 00147 } 00148 */ 00149 00150 std::ostringstream os; 00151 os << "Unexpected Element: '"; 00152 os << L(child->getNodeName()); 00153 os << "' at position "; 00154 os << getPath(); 00155 00156 _errors.push_back(os.str()); 00157 } 00158 00159 bool extractAttribute(const char * attributeName, std::ostream & os) 00160 { 00161 xercesc::DOMNode * attribute = 00162 _attributes->getNamedItem(U(attributeName)); 00163 if (!attribute) return false; 00164 os << L(attribute->getNodeValue()) << std::flush; 00165 return true; 00166 } 00167 00168 std::istream & reachableContent() 00169 { 00170 return _plainContentToParse; 00171 } 00172 00178 void fetchContent() 00179 { 00180 // _plainContentToParse.clear(); // Clear any error flag 00181 for (; _currentChild<_children->getLength(); _currentChild++) 00182 { 00183 xercesc::DOMNode * child= _children->item(_currentChild); 00184 if (child->getNodeType() == xercesc::DOMNode::COMMENT_NODE) continue; 00185 if (child->getNodeType() != xercesc::DOMNode::TEXT_NODE) break; 00186 _plainContentToParse << L(child->getNodeValue()); 00187 } 00188 _plainContentToParse << std::flush; 00189 contentLeft(); 00190 } 00191 00196 bool contentLeft() 00197 { 00198 int c = _plainContentToParse.peek(); 00199 while (not _plainContentToParse.eof()) 00200 { 00201 if (!isspace(c)) return true; 00202 _plainContentToParse.ignore(); 00203 c = _plainContentToParse.peek(); 00204 } 00205 _plainContentToParse.clear(); 00206 return false; 00207 } 00208 std::list<std::string> errors() 00209 { 00210 return _errors; 00211 } 00212 00213 std::string getPath() 00214 { 00215 std::string path; 00216 if (_parentContext) path=_parentContext->getPath(); 00217 path += '/'; 00218 path += L(_context->getNodeName()); 00219 return path; 00220 } 00221 00222 }; 00223 00224 } // Namespace CLAM 00225 00226 #endif//_XercesDomReadingContext_hxx_ 00227 00228 00229
1.7.6.1