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>
62 xercesc::XMLTranscoder* XMLInput::utf8_encoder = NULL;
63 char XMLInput::encodingbuffer[16*1024+4];
69 XMLSize_t charsReturned = utf8_encoder->transcodeTo(xercesChars,
70 xercesc::XMLString::stringLen(xercesChars),
71 (XMLByte*) encodingbuffer, 16*1024,
72 charsEaten, xercesc::XMLTranscoder::UnRep_RepChar );
73 encodingbuffer[charsReturned] = 0;
74 return encodingbuffer;
79 : parser(NULL), maxdepth(maxNestedElmnts), m_EStack(maxNestedElmnts+2),
80 numElements(-1), ignore(0), objectEnded(false),
81 abortOnDataException(true), attributes(NULL)
85 xercesc::XMLTransService::Codes resCode;
86 utf8_encoder = xercesc::XMLPlatformUtils::fgTransService->makeNewTranscoderFor(
"UTF-8", resCode, 16*1024);
87 if (!XMLInput::utf8_encoder)
88 logger <<
"Can't initialize UTF-8 transcoder: reason " << resCode << endl;
94 (
const XMLCh *
const target,
const XMLCh *
const data)
96 char* type = xercesc::XMLString::transcode(target);
97 char* value = xercesc::XMLString::transcode(data);
100 if (!strcmp(type,
"python"))
109 catch (
const DataException& e)
111 if (abortOnDataException)
113 xercesc::XMLString::release(&type);
114 xercesc::XMLString::release(&value);
117 else logger <<
"Continuing after data error: " << e.what() << endl;
120 xercesc::XMLString::release(&type);
121 xercesc::XMLString::release(&value);
125 xercesc::XMLString::release(&type);
126 xercesc::XMLString::release(&value);
132 DECLARE_EXPORT void XMLInput::startElement(
const XMLCh*
const uri,
133 const XMLCh*
const n,
const XMLCh*
const qname,
134 const xercesc::Attributes& atts)
137 assert(!states.empty());
140 if (numElements >= maxdepth)
141 throw DataException(
"XML-document with elements nested excessively deep");
144 datapair *pElement = &m_EStack[numElements+1];
145 pElement->first.reset(n);
146 pElement->second.reset();
151 switch (states.top())
160 if (pElement->first.getHash() == endingHashes.top())
170 if (!m_EHStack.empty())
171 logger <<
"Initialize root tag for reading object "
172 << getCurrentObject() <<
" ("
173 <<
typeid(*getCurrentObject()).name() <<
")" << endl;
175 logger <<
"Initialize root tag for reading object NULL" << endl;
177 states.top() = READOBJECT;
178 endingHashes.push(pElement->first.getHash());
186 logger <<
" Start element " << pElement->first.getName()
187 <<
" - object " << getCurrentObject() << endl;
191 assert(!m_EHStack.empty());
192 try {getCurrentObject()->
beginElement(*
this, pElement->first);}
193 catch (
const DataException& e)
195 if (abortOnDataException)
throw;
196 else logger <<
"Continuing after data error: " << e.what() << endl;
202 if (states.top() != IGNOREINPUT)
203 for (
unsigned int i=0, cnt=atts.getLength(); i<cnt; i++)
206 m_EStack[numElements+1].first.reset(atts.getLocalName(i));
207 m_EStack[numElements+1].second.setData(val);
209 char* attname = xercesc::XMLString::transcode(atts.getQName(i));
210 logger <<
" Processing attribute " << attname
211 <<
" - object " << getCurrentObject() << endl;
212 xercesc::XMLString::release(&attname);
214 try {getCurrentObject()->
endElement(*
this, m_EStack[numElements+1].first, m_EStack[numElements+1].second);}
215 catch (
const DataException& e)
217 if (abortOnDataException)
throw;
218 else logger <<
"Continuing after data error: " << e.what() << endl;
221 if (states.top() == IGNOREINPUT)
break;
231 const XMLCh*
const s,
232 const XMLCh*
const qname)
235 assert(numElements >= 0);
236 assert(!states.empty());
237 assert(numElements < maxdepth);
240 datapair *pElement = &(m_EStack[numElements--]);
242 switch (states.top())
246 throw LogicException(
"Unreachable code reached");
256 logger <<
" End element " << pElement->first.getName()
257 <<
" - IGNOREINPUT state" << endl;
260 if (pElement->first.getHash() != endingHashes.top())
return;
267 logger <<
"Finish IGNOREINPUT state" << endl;
277 logger <<
" End element " << pElement->first.getName()
278 <<
" - object " << getCurrentObject() << endl;
282 assert(!m_EHStack.empty());
283 if (pElement->first.getHash() == endingHashes.top())
290 getCurrentObject()->
endElement(*
this, pElement->first, pElement->second);
291 if (userexit) userexit.
call(getCurrentObject());
293 catch (
const DataException& e)
295 if (abortOnDataException)
throw;
296 else logger <<
"Continuing after data error: " << e.what() << endl;
300 logger <<
"Finish reading object " << getCurrentObject() << endl;
303 prev = getCurrentObject();
304 m_EHStack.pop_back();
309 if (m_EHStack.empty())
314 try {getCurrentObject()->
endElement(*
this, pElement->first, pElement->second);}
315 catch (
const DataException& e)
317 if (abortOnDataException)
throw;
318 else logger <<
"Continuing after data error: " << e.what() << endl;
321 logger <<
" End element " << pElement->first.getName()
322 <<
" - object " << getCurrentObject() << endl;
329 try {getCurrentObject()->
endElement(*
this, pElement->first, pElement->second);}
330 catch (
const DataException& e)
332 if (abortOnDataException)
throw;
333 else logger <<
"Continuing after data error: " << e.what() << endl;
341 #if XERCES_VERSION_MAJOR==2
342 DECLARE_EXPORT void XMLInput::characters(
const XMLCh *
const c,
const unsigned int n)
344 DECLARE_EXPORT void XMLInput::characters(
const XMLCh *
const c,
const XMLSize_t n)
348 if (states.top()==IGNOREINPUT)
return;
351 char* name = transcodeUTF8(c);
352 m_EStack[numElements].second.addData(name, strlen(name));
356 DECLARE_EXPORT void XMLInput::warning(
const xercesc::SAXParseException& e)
358 char* message = xercesc::XMLString::transcode(e.getMessage());
359 logger <<
"Warning: " << message;
360 if (e.getLineNumber() > 0)
logger <<
" at line: " << e.getLineNumber();
362 xercesc::XMLString::release(&message);
366 DECLARE_EXPORT void XMLInput::fatalError(
const xercesc::SAXParseException& e)
368 char* message = xercesc::XMLString::transcode(e.getMessage());
371 if (e.getLineNumber() > 0) ch <<
" at line " << e.getLineNumber();
372 xercesc::XMLString::release(&message);
373 throw DataException(ch.str());
377 DECLARE_EXPORT void XMLInput::error(
const xercesc::SAXParseException& e)
379 char* message = xercesc::XMLString::transcode(e.getMessage());
382 if (e.getLineNumber() > 0) ch <<
" at line " << e.getLineNumber();
383 xercesc::XMLString::release(&message);
384 throw DataException(ch.str());
391 assert(numElements >= -1);
392 endingHashes.push(m_EStack[numElements+1].first.getHash());
397 logger <<
"Start reading object " << pPI
398 <<
" (" <<
typeid(*pPI).name() <<
")" << endl;
400 prev = getCurrentObject();
401 m_EHStack.push_back(make_pair(pPI,static_cast<void*>(NULL)));
402 states.push(READOBJECT);
408 logger <<
"Start ignoring input" << endl;
410 states.push(IGNOREINPUT);
418 if (states.empty() || states.top() == SHUTDOWN)
return;
422 logger <<
" Forcing a shutdown - SHUTDOWN state" << endl;
426 states.push(SHUTDOWN);
429 if (numElements<0)
return;
435 m_EStack[numElements].first.reset(
"Not a real tag");
436 m_EStack[numElements].second.reset();
437 while (!m_EHStack.empty())
441 getCurrentObject()->
endElement(*
this, m_EStack[numElements].first, m_EStack[numElements].second);
442 if (userexit) userexit.
call(getCurrentObject());
446 if (abortOnDataException)
throw;
447 else logger <<
"Continuing after data error: " << e.what() << endl;
449 m_EHStack.pop_back();
463 if (!m_EHStack.empty())
468 if (objectEnded) m_EHStack.pop_back();
470 m_EStack[++numElements].first.reset(
"Not a real tag");
471 m_EStack[++numElements].second.reset();
472 while (!m_EHStack.empty())
476 getCurrentObject()->
endElement(*
this, m_EStack[numElements].first, m_EStack[numElements].second);
477 if (userexit) userexit.
call(getCurrentObject());
479 catch (
const DataException& e)
481 if (abortOnDataException)
throw;
482 else logger <<
"Continuing after data error: " << e.what() << endl;
484 m_EHStack.pop_back();
489 while (!states.empty()) states.pop();
490 while (!endingHashes.empty()) endingHashes.pop();
505 parser = xercesc::XMLReaderFactory::createXMLReader();
509 parser->setProperty(xercesc::XMLUni::fgXercesScannerName, const_cast<XMLCh*>
510 (validate ? xercesc::XMLUni::fgSGXMLScanner : xercesc::XMLUni::fgWFXMLScanner));
511 parser->setFeature(xercesc::XMLUni::fgSAX2CoreValidation, validate);
512 parser->setFeature(xercesc::XMLUni::fgSAX2CoreNameSpacePrefixes,
false);
513 parser->setFeature(xercesc::XMLUni::fgXercesIdentityConstraintChecking,
false);
514 parser->setFeature(xercesc::XMLUni::fgXercesDynamic,
false);
515 parser->setFeature(xercesc::XMLUni::fgXercesSchema, validate);
516 parser->setFeature(xercesc::XMLUni::fgXercesSchemaFullChecking,
false);
517 parser->setFeature(xercesc::XMLUni::fgXercesValidationErrorAsFatal,
true);
518 parser->setFeature(xercesc::XMLUni::fgXercesIgnoreAnnotations,
true);
526 XMLCh *c = xercesc::XMLString::transcode(schema.c_str());
528 xercesc::XMLUni::fgXercesSchemaExternalNoNameSpaceSchemaLocation, c
530 xercesc::XMLString::release(&c);
539 parser->setContentHandler(
this);
542 m_EHStack.push_back(make_pair(pRoot,static_cast<void*>(NULL)));
547 parser->setErrorHandler(
this);
555 catch (
const xercesc::XMLException& toCatch)
557 char* message = xercesc::XMLString::transcode(toCatch.getMessage());
559 xercesc::XMLString::release(&message);
563 catch (
const exception& toCatch)
567 msg <<
"Error during XML parsing: " << toCatch.what();
574 "Parsing error: Unexpected exception during XML parsing");
582 for (
const char* p = x.data; *p; ++p)
586 case '&': os <<
"&";
break;
587 case '<': os <<
"<";
break;
588 case '>': os <<
">";
break;
589 case '"': os <<
""";
break;
590 case '\'': os <<
"'";
break;
600 indentstring[m_nIndent++] =
'\t';
601 if (m_nIndent > 40) m_nIndent = 40;
602 indentstring[m_nIndent] =
'\0';
608 if (--m_nIndent < 0) m_nIndent = 0;
609 indentstring[m_nIndent] =
'\0';
617 if (!
object || object->
getHidden())
return;
620 const Object *previousParent = parentObject;
621 parentObject = currentObject;
622 currentObject = object;
637 currentObject = parentObject;
638 parentObject = previousParent;
650 throw LogicException(
"Can't have multiple headers in a document");
651 assert(!parentObject);
652 assert(!currentObject);
658 currentObject = object;
664 object->writeElement(
this, tag,
NOHEAD);
667 currentObject = NULL;
675 if (numObjects > 0 || !parentObject || !currentObject)
718 return i->second->getName().c_str();
725 if (name.empty())
throw LogicException(
"Creating keyword without name");
728 strStartElement = string(
"<") + name;
729 strEndElement = string(
"</") + name +
">\n";
730 strElement = string(
"<") + name +
">";
731 strAttribute = string(
" ") + name +
"=\"";
734 dw =
hash(name.c_str());
737 xercesc::XMLPlatformUtils::Initialize();
738 xmlname = xercesc::XMLString::transcode(name.c_str());
755 strStartElement = string(
"<") + nspace +
":" + name;
756 strEndElement = string(
"</") + nspace +
":" + name +
">\n";
757 strElement = string(
"<") + nspace +
":" + name +
">";
758 strAttribute = string(
" ") + nspace +
":" + name +
"=\"";
764 xercesc::XMLPlatformUtils::Initialize();
765 xmlname = xercesc::XMLString::transcode(
string(nspace +
":" + name).c_str());
772 void Keyword::check()
779 tagtable::const_iterator i =
getTags().find(dw);
780 if (i!=
getTags().end() && i->second->getName()!=strName)
782 + i->second->getName() +
" and " + strName);
783 getTags().insert(make_pair(dw,
this));
791 tagtable::iterator i =
getTags().find(dw);
795 xercesc::XMLString::release(&xmlname);
796 xercesc::XMLPlatformUtils::Terminate();
802 tagtable::const_iterator i =
getTags().find(
hash(name));
816 if (c == 0 || *c == 0)
return 0;
819 const char* curCh = c;
822 hashVal = (hashVal * 37) + (hashVal >> 24) + *curCh++;
825 return hashVal % 954991;
831 char* c = xercesc::XMLString::transcode(t);
832 if (c == 0 || *c == 0)
834 xercesc::XMLString::release(&c);
839 const char* curCh = c;
842 hashVal = (hashVal * 37) + (hashVal >> 24) + *curCh++;
845 xercesc::XMLString::release(&c);
846 return hashVal % 954991;
852 for (tagtable::iterator i =
getTags().begin(); i !=
getTags().end(); ++i)
853 logger << i->second->getName() <<
" " << i->second->dw << endl;
860 if (filename.empty())
865 if (stat(filename.c_str(), &stat_p))
868 else if (stat_p.st_mode & S_IFDIR)
874 string f = filename +
"\\*.xml";
875 WIN32_FIND_DATA dir_entry_p;
876 HANDLE h = FindFirstFile(f.c_str(), &dir_entry_p);
877 if (h == INVALID_HANDLE_VALUE)
881 f = filename +
'/' + dir_entry_p.cFileName;
884 while (FindNextFile(h, &dir_entry_p));
887 struct dirent *dir_entry_p;
888 DIR *dir_p = opendir(filename.c_str());
889 while (NULL != (dir_entry_p = readdir(dir_p)))
891 int n =
NAMLEN(dir_entry_p);
892 if (n > 4 && !strcmp(
".xml", dir_entry_p->d_name + n - 4))
894 string f = filename +
'/' + dir_entry_p->d_name;
907 XMLCh *f = xercesc::XMLString::transcode(filename.c_str());
908 xercesc::LocalFileInputSource in(f);
909 xercesc::XMLString::release(&f);