LibXmlDomReadingContext.hxx
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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;
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;
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
00138
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
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
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 }
00217
00218 #endif//_LibXmlDomReadingContext_hxx_
00219
00220
00221