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