Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

xmlconfigfile.cpp

Go to the documentation of this file.
00001 /*
00002     Sheep - A Rigid Body Dynamics Engine
00003     Copyright (C) 2001-2004 Francois Beaune
00004     Contact: http://toxicengine.sourceforge.net/
00005 
00006     This file is part of Sheep.
00007 
00008     Sheep is free software; you can redistribute it and/or modify
00009     it under the terms of the GNU General Public License as published by
00010     the Free Software Foundation; either version 2 of the License, or
00011     (at your option) any later version.
00012 
00013     Sheep is distributed in the hope that it will be useful,
00014     but WITHOUT ANY WARRANTY; without even the implied warranty of
00015     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016     GNU General Public License for more details.
00017 
00018     You should have received a copy of the GNU General Public License
00019     along with Sheep; if not, write to the Free Software
00020     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021 */
00022 
00023 #include "xmlconfigfile.h"  // include first
00024 #include "xercesmanager.h"
00025 #include "xercesutils.h"
00026 
00027 #include <pathan/XPathEvaluator.hpp>
00028 #include <pathan/XPathExpression.hpp>
00029 #include <pathan/XPathNSResolver.hpp>
00030 #include <pathan/XPathResult.hpp>
00031 #include <xercesc/sax/SAXParseException.hpp>
00032 
00033 #include <cassert>
00034 
00035 using namespace sheep;
00036 using namespace std;
00037 using namespace xercesc;
00038 
00039 XMLConfigFile::XMLConfigFile(const string &filename,
00040                              ErrorHandler *error_handler /*= 0*/)
00041 {
00042     initialize(
00043         filename,
00044         "",     // no validation
00045         error_handler
00046     );
00047 }
00048 
00049 XMLConfigFile::XMLConfigFile(const string &filename,
00050                              const string &schema_filename,
00051                              ErrorHandler *error_handler /*= 0*/)
00052 {
00053     initialize(
00054         filename,
00055         schema_filename,
00056         error_handler
00057     );
00058 }
00059 
00060 XMLConfigFile::~XMLConfigFile() {
00061     delete m_nsresolver;
00062     delete m_evaluator;
00063     delete m_parser;
00064 
00065     XercesManager::Shutdown();
00066 }
00067 
00068 int XMLConfigFile::Count(const string &xpathexpr) const {
00069     XPathResult *result = query(xpathexpr);
00070 
00071     assert(result);
00072 
00073     return result->getSnapshotLength();
00074 }
00075 
00076 namespace {
00077     class DefaultErrorHandler : public ErrorHandler {
00078     public:
00079         virtual void warning(const SAXParseException &e) {
00080             throw XMLConfigFile::ParseErrorException(StrX(e.getMessage()));
00081         }
00082 
00083         virtual void error(const SAXParseException &e) {
00084             throw XMLConfigFile::ParseErrorException(StrX(e.getMessage()));
00085         }
00086 
00087         virtual void fatalError(const SAXParseException &e) {
00088             throw XMLConfigFile::ParseErrorException(StrX(e.getMessage()));
00089         }
00090 
00091         virtual void resetErrors() {}
00092     };
00093 }
00094 
00095 void XMLConfigFile::initialize(const string &filename,
00096                                const string &schema_filename,
00097                                ErrorHandler *error_handler)
00098 {
00099     XercesManager::Initialize();
00100 
00101     // Create the parser.
00102     m_parser = new XercesDOMParser();
00103 
00104     // Configure the parser.
00105     if(schema_filename.size() > 0) {
00106         m_parser->setValidationScheme(XercesDOMParser::Val_Always);
00107         m_parser->setDoNamespaces(true);
00108         m_parser->setDoSchema(true);
00109         m_parser->setValidationSchemaFullChecking(true);
00110         m_parser->setExternalNoNamespaceSchemaLocation(schema_filename.c_str());
00111     } else {
00112         m_parser->setValidationScheme(XercesDOMParser::Val_Never);
00113     }
00114 
00115     // Install the provided error handler, or the default error handler if none is provided.
00116     ErrorHandler *default_error_handler = 0;
00117     if(error_handler)
00118         m_parser->setErrorHandler(error_handler);
00119     else {
00120         default_error_handler = new DefaultErrorHandler();
00121         m_parser->setErrorHandler(default_error_handler);
00122     }
00123 
00124     // Parse the XML file and create the DOM document.
00125     try {
00126         m_parser->parse(filename.c_str());
00127     }
00128     catch(const XMLException &e) {
00129         throw ParseErrorException(StrX(e.getMessage()));
00130     }
00131     catch(const DOMException &e) {
00132         throw ParseErrorException(StrX(e.msg));
00133     }
00134 
00135     // Delete the default error handler if one has been created.
00136     delete default_error_handler;
00137 
00138     // Get the root element of the document.
00139     m_rootelement = m_parser->getDocument()->getDocumentElement();
00140 
00141     // Create an XPathEvaluator class. This class is used as a factory for creating
00142     // XPathExpression and XPathNSResolver (it is rarely used for evaluation in the
00143     // latest spec [31/10/2001], however, and is somewhat misnamed).
00144     m_evaluator = XPathEvaluator::createEvaluator();
00145 
00146     // Create an XPathNSResolver using the XPathEvaluator factory class. The
00147     // XPathNSResolver class binds XML namespace prefixes to the full namespace string.
00148     m_nsresolver = m_evaluator->createNSResolver(m_rootelement);
00149 }
00150 
00151 XPathResult *XMLConfigFile::query(const string &xpathexpr) const {
00152     // Create an XPathExpression using the XPathEvaluator factory class.
00153     // Pass as parameters the XPath expression and the appropriate XPathNSResolver.
00154     // The XPath request any childNode nodes off the parentNode who have a subchildNode child.
00155     XPathExpression *parsed_expression;
00156     try {
00157         parsed_expression = m_evaluator->createExpression(
00158             XStr(xpathexpr),
00159             m_nsresolver
00160         );
00161     }
00162     catch(const XPathException &e) {
00163         throw QueryErrorException(e.getString());
00164     }
00165 
00166     // The XPath expression is parsed and stored. It may now be applied to any number of documents.
00167     // The parsed expression is evaluated on the document. We request a
00168     // node set as output. The result is placed in the variable result.
00169     XPathResult *result = 0;    // keep the compiler happy, because we pass this variable
00170                                 // to the XPathExpression::evaluate() method (for unknown reasons)
00171     try {
00172         result = parsed_expression->evaluate(
00173             m_rootelement,
00174             XPathResult::ORDERED_NODE_SNAPSHOT_TYPE,
00175             result  // don't know why we must pass this argument, it is not actually used by the method
00176         );
00177     }
00178     catch(const XPathException &e) {
00179         throw QueryErrorException(e.getString());
00180     }
00181 
00182     return result;
00183 }
00184 
00185 string XMLConfigFile::get_string(const string &xpathexpr) const {
00186     XPathResult *result = query(xpathexpr);
00187 
00188     if(result->getSnapshotLength() != 1)
00189         throw QueryErrorException("Query resulted in zero or multiple answers.");
00190 
00191     return StrX(result->snapshotItem(0)->getNodeValue());
00192 }

Generated on Tue May 11 01:31:53 2004 for toxic by doxygen 1.3.6