31 #define WIN32_LEAN_AND_MEAN
37 # define NAMLEN(dirent) strlen((dirent)->d_name)
39 # define dirent direct
40 # define NAMLEN(dirent) (dirent)->d_namlen
42 # include <sys/ndir.h>
65 (
const XMLCh *
const target,
const XMLCh *
const data)
67 char* type = xercesc::XMLString::transcode(target);
68 char* value = xercesc::XMLString::transcode(data);
71 if (!strcmp(type,
"python"))
80 catch (
const DataException& e)
82 if (abortOnDataException)
84 xercesc::XMLString::release(&type);
85 xercesc::XMLString::release(&value);
88 else logger <<
"Continuing after data error: " << e.what() << endl;
91 xercesc::XMLString::release(&type);
92 xercesc::XMLString::release(&value);
96 xercesc::XMLString::release(&type);
97 xercesc::XMLString::release(&value);
103 DECLARE_EXPORT void XMLInput::startElement(
const XMLCh*
const uri,
104 const XMLCh*
const n,
const XMLCh*
const qname,
105 const xercesc::Attributes& atts)
108 assert(!states.empty());
111 if (numElements >= maxdepth)
112 throw DataException(
"XML-document with elements nested excessively deep");
115 datapair *pElement = &m_EStack[numElements+1];
116 pElement->first.reset(n);
117 pElement->second.reset();
122 switch (states.top())
131 if (pElement->first.getHash() == endingHashes.top())
141 if (!m_EHStack.empty())
142 logger <<
"Initialize root tag for reading object "
143 << getCurrentObject() <<
" ("
144 <<
typeid(*getCurrentObject()).name() <<
")" << endl;
146 logger <<
"Initialize root tag for reading object NULL" << endl;
148 states.top() = READOBJECT;
149 endingHashes.push(pElement->first.getHash());
157 logger <<
" Start element " << pElement->first.getName()
158 <<
" - object " << getCurrentObject() << endl;
162 assert(!m_EHStack.empty());
163 try {getCurrentObject()->
beginElement(*
this, pElement->first);}
164 catch (
const DataException& e)
166 if (abortOnDataException)
throw;
167 else logger <<
"Continuing after data error: " << e.what() << endl;
173 if (states.top() != IGNOREINPUT)
174 for (
unsigned int i=0, cnt=atts.getLength(); i<cnt; i++)
176 char* val = xercesc::XMLString::transcode(atts.getValue(i));
177 m_EStack[numElements+1].first.reset(atts.getLocalName(i));
178 m_EStack[numElements+1].second.setData(val);
180 char* attname = xercesc::XMLString::transcode(atts.getQName(i));
181 logger <<
" Processing attribute " << attname
182 <<
" - object " << getCurrentObject() << endl;
183 xercesc::XMLString::release(&attname);
185 try {getCurrentObject()->
endElement(*
this, m_EStack[numElements+1].first, m_EStack[numElements+1].second);}
186 catch (
const DataException& e)
188 if (abortOnDataException)
throw;
189 else logger <<
"Continuing after data error: " << e.what() << endl;
191 xercesc::XMLString::release(&val);
193 if (states.top() == IGNOREINPUT)
break;
203 const XMLCh*
const s,
204 const XMLCh*
const qname)
207 assert(numElements >= 0);
208 assert(!states.empty());
209 assert(numElements < maxdepth);
212 datapair *pElement = &(m_EStack[numElements--]);
214 switch (states.top())
218 throw LogicException(
"Unreachable code reached");
228 logger <<
" End element " << pElement->first.getName()
229 <<
" - IGNOREINPUT state" << endl;
232 if (pElement->first.getHash() != endingHashes.top())
return;
239 logger <<
"Finish IGNOREINPUT state" << endl;
249 logger <<
" End element " << pElement->first.getName()
250 <<
" - object " << getCurrentObject() << endl;
254 assert(!m_EHStack.empty());
255 if (pElement->first.getHash() == endingHashes.top())
262 getCurrentObject()->
endElement(*
this, pElement->first, pElement->second);
263 if (userexit) userexit.
call(getCurrentObject());
265 catch (
const DataException& e)
267 if (abortOnDataException)
throw;
268 else logger <<
"Continuing after data error: " << e.what() << endl;
272 logger <<
"Finish reading object " << getCurrentObject() << endl;
275 prev = getCurrentObject();
276 m_EHStack.pop_back();
281 if (m_EHStack.empty())
286 try {getCurrentObject()->
endElement(*
this, pElement->first, pElement->second);}
287 catch (
const DataException& e)
289 if (abortOnDataException)
throw;
290 else logger <<
"Continuing after data error: " << e.what() << endl;
293 logger <<
" End element " << pElement->first.getName()
294 <<
" - object " << getCurrentObject() << endl;
301 try {getCurrentObject()->
endElement(*
this, pElement->first, pElement->second);}
302 catch (
const DataException& e)
304 if (abortOnDataException)
throw;
305 else logger <<
"Continuing after data error: " << e.what() << endl;
313 #if XERCES_VERSION_MAJOR==2
314 DECLARE_EXPORT void XMLInput::characters(
const XMLCh *
const c,
const unsigned int n)
316 DECLARE_EXPORT void XMLInput::characters(
const XMLCh *
const c,
const XMLSize_t n)
320 if (states.top()==IGNOREINPUT)
return;
323 char* name = xercesc::XMLString::transcode(c);
324 m_EStack[numElements].second.addData(name, strlen(name));
325 xercesc::XMLString::release(&name);
329 DECLARE_EXPORT void XMLInput::warning(
const xercesc::SAXParseException& e)
331 char* message = xercesc::XMLString::transcode(e.getMessage());
332 logger <<
"Warning: " << message;
333 if (e.getLineNumber() > 0)
logger <<
" at line: " << e.getLineNumber();
335 xercesc::XMLString::release(&message);
339 DECLARE_EXPORT void XMLInput::fatalError(
const xercesc::SAXParseException& e)
341 char* message = xercesc::XMLString::transcode(e.getMessage());
344 if (e.getLineNumber() > 0) ch <<
" at line " << e.getLineNumber();
345 xercesc::XMLString::release(&message);
346 throw DataException(ch.str());
350 DECLARE_EXPORT void XMLInput::error(
const xercesc::SAXParseException& e)
352 char* message = xercesc::XMLString::transcode(e.getMessage());
355 if (e.getLineNumber() > 0) ch <<
" at line " << e.getLineNumber();
356 xercesc::XMLString::release(&message);
357 throw DataException(ch.str());
364 assert(numElements >= -1);
365 endingHashes.push(m_EStack[numElements+1].first.getHash());
370 logger <<
"Start reading object " << pPI
371 <<
" (" <<
typeid(*pPI).name() <<
")" << endl;
373 prev = getCurrentObject();
374 m_EHStack.push_back(make_pair(pPI,static_cast<void*>(NULL)));
375 states.push(READOBJECT);
381 logger <<
"Start ignoring input" << endl;
383 states.push(IGNOREINPUT);
391 if (states.empty() || states.top() == SHUTDOWN)
return;
395 logger <<
" Forcing a shutdown - SHUTDOWN state" << endl;
399 states.push(SHUTDOWN);
402 if (numElements<0)
return;
408 m_EStack[numElements].first.reset(
"Not a real tag");
409 m_EStack[numElements].second.reset();
410 while (!m_EHStack.empty())
414 getCurrentObject()->
endElement(*
this, m_EStack[numElements].first, m_EStack[numElements].second);
415 if (userexit) userexit.
call(getCurrentObject());
419 if (abortOnDataException)
throw;
420 else logger <<
"Continuing after data error: " << e.what() << endl;
422 m_EHStack.pop_back();
436 if (!m_EHStack.empty())
441 if (objectEnded) m_EHStack.pop_back();
443 m_EStack[++numElements].first.reset(
"Not a real tag");
444 m_EStack[++numElements].second.reset();
445 while (!m_EHStack.empty())
449 getCurrentObject()->
endElement(*
this, m_EStack[numElements].first, m_EStack[numElements].second);
450 if (userexit) userexit.
call(getCurrentObject());
452 catch (
const DataException& e)
454 if (abortOnDataException)
throw;
455 else logger <<
"Continuing after data error: " << e.what() << endl;
457 m_EHStack.pop_back();
462 while (!states.empty()) states.pop();
463 while (!endingHashes.empty()) endingHashes.pop();
478 parser = xercesc::XMLReaderFactory::createXMLReader();
482 parser->setProperty(xercesc::XMLUni::fgXercesScannerName, const_cast<XMLCh*>
483 (validate ? xercesc::XMLUni::fgSGXMLScanner : xercesc::XMLUni::fgWFXMLScanner));
484 parser->setFeature(xercesc::XMLUni::fgSAX2CoreValidation, validate);
485 parser->setFeature(xercesc::XMLUni::fgSAX2CoreNameSpacePrefixes,
false);
486 parser->setFeature(xercesc::XMLUni::fgXercesIdentityConstraintChecking,
false);
487 parser->setFeature(xercesc::XMLUni::fgXercesDynamic,
false);
488 parser->setFeature(xercesc::XMLUni::fgXercesSchema, validate);
489 parser->setFeature(xercesc::XMLUni::fgXercesSchemaFullChecking,
false);
490 parser->setFeature(xercesc::XMLUni::fgXercesValidationErrorAsFatal,
true);
491 parser->setFeature(xercesc::XMLUni::fgXercesIgnoreAnnotations,
true);
499 XMLCh *c = xercesc::XMLString::transcode(schema.c_str());
501 xercesc::XMLUni::fgXercesSchemaExternalNoNameSpaceSchemaLocation, c
503 xercesc::XMLString::release(&c);
512 parser->setContentHandler(
this);
515 m_EHStack.push_back(make_pair(pRoot,static_cast<void*>(NULL)));
520 parser->setErrorHandler(
this);
528 catch (
const xercesc::XMLException& toCatch)
530 char* message = xercesc::XMLString::transcode(toCatch.getMessage());
532 xercesc::XMLString::release(&message);
536 catch (
const exception& toCatch)
540 msg <<
"Error during XML parsing: " << toCatch.what();
547 "Parsing error: Unexpected exception during XML parsing");
555 for (
const char* p = x.data; *p; ++p)
559 case '&': os <<
"&";
break;
560 case '<': os <<
"<";
break;
561 case '>': os <<
">";
break;
562 case '"': os <<
""";
break;
563 case '\'': os <<
"'";
break;
573 indentstring[m_nIndent++] =
'\t';
574 if (m_nIndent > 40) m_nIndent = 40;
575 indentstring[m_nIndent] =
'\0';
581 if (--m_nIndent < 0) m_nIndent = 0;
582 indentstring[m_nIndent] =
'\0';
590 if (!
object || object->
getHidden())
return;
593 const Object *previousParent = parentObject;
594 parentObject = currentObject;
595 currentObject = object;
610 currentObject = parentObject;
611 parentObject = previousParent;
623 throw LogicException(
"Can't have multiple headers in a document");
624 assert(!parentObject);
625 assert(!currentObject);
631 currentObject = object;
637 object->writeElement(
this, tag,
NOHEADER);
640 currentObject = NULL;
648 if (numObjects > 0 || !parentObject || !currentObject)
662 char* s = xercesc::XMLString::transcode(atts->getValue(key.
getXMLCharacters()));
664 xercesc::XMLString::release(&s);
692 return i->second->getName().c_str();
699 if (name.empty())
throw LogicException(
"Creating keyword without name");
702 strStartElement = string(
"<") + name;
703 strEndElement = string(
"</") + name +
">\n";
704 strElement = string(
"<") + name +
">";
705 strAttribute = string(
" ") + name +
"=\"";
708 dw =
hash(name.c_str());
711 xercesc::XMLPlatformUtils::Initialize();
712 xmlname = xercesc::XMLString::transcode(name.c_str());
729 strStartElement = string(
"<") + nspace +
":" + name;
730 strEndElement = string(
"</") + nspace +
":" + name +
">\n";
731 strElement = string(
"<") + nspace +
":" + name +
">";
732 strAttribute = string(
" ") + nspace +
":" + name +
"=\"";
738 xercesc::XMLPlatformUtils::Initialize();
739 xmlname = xercesc::XMLString::transcode(
string(nspace +
":" + name).c_str());
746 void Keyword::check()
753 tagtable::const_iterator i =
getTags().find(dw);
754 if (i!=
getTags().end() && i->second->getName()!=strName)
756 + i->second->getName() +
" and " + strName);
757 getTags().insert(make_pair(dw,
this));
765 tagtable::iterator i =
getTags().find(dw);
769 xercesc::XMLString::release(&xmlname);
770 xercesc::XMLPlatformUtils::Terminate();
776 tagtable::const_iterator i =
getTags().find(
hash(name));
790 if (c == 0 || *c == 0)
return 0;
793 const char* curCh = c;
796 hashVal = (hashVal * 38) + (hashVal >> 24) + *curCh++;
799 return hashVal % 954991;
805 char* c = xercesc::XMLString::transcode(t);
806 if (c == 0 || *c == 0)
808 xercesc::XMLString::release(&c);
813 const char* curCh = c;
816 hashVal = (hashVal * 38) + (hashVal >> 24) + *curCh++;
819 xercesc::XMLString::release(&c);
820 return hashVal % 954991;
826 for (tagtable::iterator i =
getTags().begin(); i !=
getTags().end(); ++i)
827 logger << i->second->getName() <<
" " << i->second->dw << endl;
834 if (filename.empty())
839 if (stat(filename.c_str(), &stat_p))
842 else if (stat_p.st_mode & S_IFDIR)
848 string f = filename +
"\\*.xml";
849 WIN32_FIND_DATA dir_entry_p;
850 HANDLE h = FindFirstFile(f.c_str(), &dir_entry_p);
851 if (h == INVALID_HANDLE_VALUE)
855 f = filename +
'/' + dir_entry_p.cFileName;
858 while (FindNextFile(h, &dir_entry_p));
861 struct dirent *dir_entry_p;
862 DIR *dir_p = opendir(filename.c_str());
863 while (NULL != (dir_entry_p = readdir(dir_p)))
865 int n =
NAMLEN(dir_entry_p);
866 if (n > 4 && !strcmp(
".xml", dir_entry_p->d_name + n - 4))
868 string f = filename +
'/' + dir_entry_p->d_name;
881 XMLCh *f = xercesc::XMLString::transcode(filename.c_str());
882 xercesc::LocalFileInputSource in(f);
883 xercesc::XMLString::release(&f);