XercesDomReadingContext.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 _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
00053 public:
00054 XercesDomReadingContext(xercesc::DOMElement * element)
00055 {
00056 _parentContext=0;
00057 setAt(element);
00058 }
00059
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;
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;
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
00145
00146
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
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 }
00225
00226 #endif//_XercesDomReadingContext_hxx_
00227
00228
00229