CLAM-Development  1.4.0
XercesDomReadingContext.hxx
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2001-2004 MUSIC TECHNOLOGY GROUP (MTG)
3  * UNIVERSITAT POMPEU FABRA
4  *
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  */
21 
22 #ifndef _XercesDomReadingContext_hxx_
23 #define _XercesDomReadingContext_hxx_
24 
25 #include "Assert.hxx"
26 #include "XercesEncodings.hxx"
27 #include <xercesc/dom/DOMElement.hpp>
28 #include <xercesc/dom/DOMNamedNodeMap.hpp>
29 #include <xercesc/dom/DOMNodeList.hpp>
30 #include <sstream>
31 #include <list>
32 #include <string>
33 
34 namespace CLAM
35 {
36 class XercesDomDocumentHandler;
37 
43 {
44  xercesc::DOMElement * _context;
45  xercesc::DOMNodeList * _children;
46  xercesc::DOMNamedNodeMap * _attributes;
47  std::stringstream _plainContentToParse;
48  unsigned int _currentChild;
49  XercesDomReadingContext * _parentContext;
50  std::list<std::string> _errors;
51 
52 // std::list<std::string> & _currentPath;
53 public:
54  XercesDomReadingContext(xercesc::DOMElement * element)
55  {
56  _parentContext=0;
57  setAt(element);
58  }
59  // TODO: Test this
61 
62  XercesDomReadingContext(XercesDomReadingContext * oldContext, const char * name)
63  {
64  _parentContext=oldContext;
65  setAt(oldContext->fetchElement(name));
66  }
67  void setAt(xercesc::DOMElement * element)
68  {
69  _context = element;
70  _children = _context->getChildNodes();
71  _attributes = _context->getAttributes();
72  _currentChild=0;
73  fetchContent();
74  }
75 
84  bool findElement(const char * name)
85  {
86  if (contentLeft()) return false;
87  if (_currentChild==_children->getLength()) return false; // No nodes left
88 
89  xercesc::DOMNode * child = _children->item(_currentChild);
90  CLAM_ASSERT(child->getNodeType() == xercesc::DOMNode::ELEMENT_NODE,
91  "Can't change the context to a non element node");
92  if (!xercesc::XMLString::equals(child->getNodeName(), U(name))) return false; // Name mismatch
93  return true;
94  }
95 
103  xercesc::DOMElement * fetchElement(const char * name)
104  {
105  bool hasContentLeft;
106  hasContentLeft = contentLeft();
107  CLAM_ASSERT(!hasContentLeft, "Fetching element with content left");
108  CLAM_ASSERT(_currentChild!=_children->getLength(),
109  "Accessing beyond DOM nodes");
110  xercesc::DOMNode * child = _children->item(_currentChild);
111  CLAM_ASSERT(child->getNodeType() == xercesc::DOMNode::ELEMENT_NODE,
112  "Can't change the context to a non element node");
113  CLAM_ASSERT(xercesc::XMLString::equals(child->getNodeName(), U(name)),
114  "XML element name should be the one expected");
115  _currentChild++;
116  fetchContent();
117  return dynamic_cast<xercesc::DOMElement *>(child);
118  }
119 
121  {
124  return _parentContext;
125  }
126 
128  {
129  if (!contentLeft()) return;
130  std::ostringstream os;
131  os << "Unexpected content: '";
132  for (int c=_plainContentToParse.get(); not _plainContentToParse.eof(); c=_plainContentToParse.get())
133  os.put(c);
134  os << "' at position ";
135  os << getPath();
136  _errors.push_back(os.str());
137  }
138 
140  {
141  if (_currentChild>=_children->getLength()) return;
142  xercesc::DOMNode * child = _children->item(_currentChild);
143  /*
144  if (child->getNodeType() != xercesc::DOMNode::ELEMENT_NODE)
145  {
146  _errors.push_back("Unexpected node type");
147  }
148  */
149 
150  std::ostringstream os;
151  os << "Unexpected Element: '";
152  os << L(child->getNodeName());
153  os << "' at position ";
154  os << getPath();
155 
156  _errors.push_back(os.str());
157  }
158 
159  bool extractAttribute(const char * attributeName, std::ostream & os)
160  {
161  xercesc::DOMNode * attribute =
162  _attributes->getNamedItem(U(attributeName));
163  if (!attribute) return false;
164  os << L(attribute->getNodeValue()) << std::flush;
165  return true;
166  }
167 
168  std::istream & reachableContent()
169  {
170  return _plainContentToParse;
171  }
172 
179  {
180 // _plainContentToParse.clear(); // Clear any error flag
181  for (; _currentChild<_children->getLength(); _currentChild++)
182  {
183  xercesc::DOMNode * child= _children->item(_currentChild);
184  if (child->getNodeType() == xercesc::DOMNode::COMMENT_NODE) continue;
185  if (child->getNodeType() != xercesc::DOMNode::TEXT_NODE) break;
186  _plainContentToParse << L(child->getNodeValue());
187  }
188  _plainContentToParse << std::flush;
189  contentLeft();
190  }
191 
196  bool contentLeft()
197  {
198  int c = _plainContentToParse.peek();
199  while (not _plainContentToParse.eof())
200  {
201  if (!isspace(c)) return true;
202  _plainContentToParse.ignore();
203  c = _plainContentToParse.peek();
204  }
205  _plainContentToParse.clear();
206  return false;
207  }
208  std::list<std::string> errors()
209  {
210  return _errors;
211  }
212 
213  std::string getPath()
214  {
215  std::string path;
216  if (_parentContext) path=_parentContext->getPath();
217  path += '/';
218  path += L(_context->getNodeName());
219  return path;
220  }
221 
222 };
223 
224 } // Namespace CLAM
225 
226 #endif//_XercesDomReadingContext_hxx_
227 
228 
229