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