LibXmlDomReadingContext.hxx

Go to the documentation of this file.
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 
Generated by  doxygen 1.6.3