00001 #include "XercesLoader.h"
00002 #include "XercesFileElement.h"
00003 #include "NodeCreationProxy.h"
00004 #include "X3DAbstractNode.h"
00005 #include "Scene.h"
00006
00007 #include <xercesc/util/XMLString.hpp>
00008 #include <xercesc/sax2/DefaultHandler.hpp>
00009 #include <xercesc/sax2/XMLReaderFactory.hpp>
00010 #include <xercesc/util/PlatformUtils.hpp>
00011
00012 #include <iostream>
00013
00014 using namespace X3DTK;
00015 using namespace std;
00016 XERCES_CPP_NAMESPACE_USE
00017
00018 namespace X3DTK {
00019
00020 class SAX2X3DHandler : public DefaultHandler
00021 {
00022 public:
00023 SAX2X3DHandler(NodeCreationProxy *nodeCreationProxy);
00024 ~SAX2X3DHandler();
00025
00026 void startDocument();
00027 void startElement(const XMLCh* const uri, const XMLCh* const localname, const XMLCh* const qname, const XERCES_CPP_NAMESPACE_QUALIFIER Attributes &attrs);
00028 void endElement(const XMLCh *const uri, const XMLCh *const localname, const XMLCh *const qname);
00029 void endDocument();
00030 void fatalError(const XERCES_CPP_NAMESPACE_QUALIFIER SAXParseException& exception);
00031 void error(const XERCES_CPP_NAMESPACE_QUALIFIER SAXParseException& exception);
00032
00033 inline Scene *getScene() const {return _scene;};
00034
00035 private:
00036 MFNode _nodeStack;
00037 Scene *_scene;
00038 NodeCreationProxy *_ncp;
00039 bool _sceneDescription;
00040 unsigned int _depth;
00041 };
00042
00043 }
00044
00045 X3DTK::SAX2X3DHandler::SAX2X3DHandler(NodeCreationProxy *nodeCreationProxy)
00046 : _scene(0), _ncp(nodeCreationProxy), _sceneDescription(false), _depth(0)
00047 {
00048 }
00049
00050 X3DTK::SAX2X3DHandler::~SAX2X3DHandler()
00051 {
00052 }
00053
00054 void X3DTK::SAX2X3DHandler::startDocument()
00055 {
00056 _scene = 0;
00057 _sceneDescription = false;
00058 _depth = 0;
00059 }
00060
00061 void X3DTK::SAX2X3DHandler::startElement(const XMLCh* const uri, const XMLCh* const localname, const XMLCh* const qname, const Attributes &attrs)
00062 {
00063
00064
00065 if (_depth == 0)
00066 {
00067 XercesFileElement e(XMLString::transcode(qname), &attrs);
00068
00069 int index;
00070 if (_sceneDescription)
00071 {
00072 SFNode Father = _nodeStack.back();
00073 SFNode N;
00074 index = e.getIndexAttribute("USE");
00075
00076 if (index != -1)
00077 {
00078 N = X3DAbstractNode::DEFDict.getNodeOfName(e.getAttribute(index));
00079 }
00080 else
00081 {
00082 N = _ncp->createFromName(e.getName());
00083 if (N == 0)
00084 {
00085 _depth = 1;
00086 return;
00087 }
00088 N->loadAttributes(&e);
00089 }
00090 index = e.getIndexAttribute("DEF");
00091 if (index != -1)
00092 X3DAbstractNode::DEFDict.insert(e.getAttribute(index), N);
00093
00094 Father->setChild(N);
00095 _nodeStack.push_back(N);
00096 }
00097
00098 if (e.getName() == "Scene")
00099 {
00100 _sceneDescription = true;
00101 _scene = new Scene();
00102 _nodeStack.push_back(_scene);
00103 }
00104 }
00105 else
00106 ++_depth;
00107 }
00108
00109 void X3DTK::SAX2X3DHandler::endElement(const XMLCh *const uri, const XMLCh *const localname, const XMLCh *const qname)
00110 {
00111 if (_sceneDescription)
00112 {
00113 if ((_depth == 0) && (_nodeStack.size() > 0))
00114 _nodeStack.pop_back();
00115 else
00116 --_depth;
00117 }
00118 }
00119
00120 void X3DTK::SAX2X3DHandler::endDocument()
00121 {
00122 X3DAbstractNode::DEFDict.makeDEFNonAmbiguous();
00123 _nodeStack.clear();
00124 }
00125
00126 void X3DTK::SAX2X3DHandler::error(const SAXParseException& exception)
00127 {
00128 char* message = XMLString::transcode(exception.getMessage());
00129 cout << "Error: " << message
00130 << " at line: " << exception.getLineNumber()
00131 << endl;
00132 }
00133
00134 void X3DTK::SAX2X3DHandler::fatalError(const SAXParseException& exception)
00135 {
00136 char* message = XMLString::transcode(exception.getMessage());
00137 cout << "Fatal Error: " << message
00138 << " at line: " << exception.getLineNumber()
00139 << endl;
00140 }
00141
00142 class X3DTK::XercesLoaderImplementation
00143 {
00144 public:
00145 XercesLoaderImplementation(){};
00146
00147 XERCES_CPP_NAMESPACE_QUALIFIER SAX2XMLReader* _parser;
00148 SAX2X3DHandler *_handler;
00149 };
00150
00151 XercesLoader::XercesLoader(NodeCreationProxy *nodeCreationProxy)
00152 : _impl(new XercesLoaderImplementation())
00153 {
00154 ncp = nodeCreationProxy;
00155
00156 try
00157 {
00158 XMLPlatformUtils::Initialize();
00159 }
00160 catch (const XMLException& toCatch)
00161 {
00162 char* message = XMLString::transcode(toCatch.getMessage());
00163 cout << "Error during initialization! :\n";
00164 cout << "Exception message is: \n" << message << "\n";
00165 XMLString::release(&message);
00166 }
00167
00168 _impl->_parser = XMLReaderFactory::createXMLReader();
00169 _impl->_parser->setFeature(XMLUni::fgSAX2CoreNameSpaces, true);
00170 _impl->_parser->setFeature(XMLUni::fgXercesSchemaFullChecking, false);
00171 _impl->_parser->setFeature(XMLUni::fgSAX2CoreNameSpacePrefixes, false);
00172
00173 _impl->_handler = new SAX2X3DHandler(nodeCreationProxy);
00174 _impl->_parser->setContentHandler(_impl->_handler);
00175 _impl->_parser->setErrorHandler(_impl->_handler);
00176 _impl->_parser->setDTDHandler(_impl->_handler);
00177 }
00178
00179 XercesLoader::~XercesLoader()
00180 {
00181 delete _impl->_parser;
00182 delete _impl->_handler;
00183 }
00184
00185 Scene *XercesLoader::load(const char *file, bool fileValidation) const
00186 {
00187 if (fileValidation)
00188 {
00189 _impl->_parser->setFeature(XMLUni::fgXercesLoadExternalDTD, true);
00190 _impl->_parser->setFeature(XMLUni::fgXercesSchema, true);
00191 _impl->_parser->setFeature(XMLUni::fgSAX2CoreValidation, true);
00192 }
00193 else
00194 {
00195 _impl->_parser->setFeature(XMLUni::fgXercesLoadExternalDTD, false);
00196 _impl->_parser->setFeature(XMLUni::fgXercesSchema, false);
00197 _impl->_parser->setFeature(XMLUni::fgSAX2CoreValidation, false);
00198 }
00199
00200 try
00201 {
00202 _impl->_parser->parse(file);
00203 }
00204 catch (const XMLException& toCatch)
00205 {
00206 char* message = XMLString::transcode(toCatch.getMessage());
00207 cout << "Exception message is: \n"
00208 << message << "\n";
00209 XMLString::release(&message);
00210 }
00211 catch (const SAXParseException& toCatch)
00212 {
00213 char* message = XMLString::transcode(toCatch.getMessage());
00214 cout << "Exception message is: \n"
00215 << message << "\n";
00216 XMLString::release(&message);
00217 }
00218 catch (...)
00219 {
00220 cout << "Unexpected Exception \n" ;
00221 }
00222
00223 Scene *scene = _impl->_handler->getScene();
00224 if (scene != 0)
00225 scene->setFileName(file);
00226
00227 return scene;
00228 }
00229