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