arabica/SAX/wrappers/saxxerces.h

1171 lines
42 KiB
C
Raw Normal View History

2003-09-11 12:26:53 +02:00
#ifndef ARABICA_SAX_XERCES_H
#define ARABICA_SAX_XERCES_H
2002-06-21 13:16:28 +02:00
//---------------------------------------------------------------------------
// A SAX2 wrapper class for Xerces.
//
// $Id$
//---------------------------------------------------------------------------
2003-09-12 16:09:13 +02:00
// Debugging code for the doSetProperty and doGetProperty methods.
// Since these methods use runtime casting, it is often helpful to
// know the exact type of a method's arguments to compare with
// what is expected. This is hard, even with current (2003)
// debuggers, so this code can print it out, assuming you've
// compiled with gcc 3.2
//
// Example usage is given in doSetProperty
// Use only with GCC 3.2
#ifdef SAXXERCES_DEBUG
#include <iostream>
#include <typeinfo>
#include <cxxabi.h>
// Demangle Run-Time Type Information std::type_info struct.
std::ostream& operator<<(std::ostream& o, const std::type_info& ti)
{
int status;
char *realname = abi::__cxa_demangle(ti.name(), 0, 0, &status);
if (status != 0)
o.setstate(std::ios_base::failbit);
o << realname;
free(realname);
return o;
}
#endif
#include <iterator>
#include <memory>
#include <string>
#include <vector>
#include <SAX/Attributes.h>
2002-06-21 13:16:28 +02:00
#include <SAX/InputSource.h>
#include <SAX/XMLReader.h>
2003-09-12 16:09:13 +02:00
#include <SAX/ext/ProgressiveParser.h>
2002-06-21 13:16:28 +02:00
#include <SAX/SAXParseException.h>
2002-07-16 14:33:29 +02:00
#include <SAX/SAXNotRecognizedException.h>
#include <SAX/SAXNotSupportedException.h>
2002-06-21 13:16:28 +02:00
#include <SAX/ext/LexicalHandler.h>
#include <SAX/ext/DeclHandler.h>
2003-09-12 16:09:13 +02:00
#include <SAX/IStreamHandle.h>
#include <SAX/wrappers/XercesPropertyNames.h>
#include <SAX/wrappers/XercesFeatureNames.h>
2002-06-21 13:16:28 +02:00
// Xerces Includes
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/sax2/SAX2XMLReader.hpp>
#include <xercesc/sax2/XMLReaderFactory.hpp>
#include <xercesc/sax2/ContentHandler.hpp>
#include <xercesc/sax2/LexicalHandler.hpp>
#include <xercesc/sax2/DeclHandler.hpp>
2003-09-12 16:09:13 +02:00
#include <xercesc/sax/EntityResolver.hpp>
2002-06-21 13:16:28 +02:00
#include <xercesc/sax/DTDHandler.hpp>
#include <xercesc/sax/ErrorHandler.hpp>
#include <xercesc/sax/SAXParseException.hpp>
#include <xercesc/util/BinInputStream.hpp>
#include <xercesc/sax/InputSource.hpp>
2003-09-12 16:09:13 +02:00
#include <xercesc/util/TransService.hpp>
#ifndef XERCES_HAS_CPP_NAMESPACE
#define XERCES_CPP_NAMESPACE
#endif
2002-06-21 13:16:28 +02:00
namespace SAX
{
2003-09-12 16:09:13 +02:00
namespace XercesImpl
{
2003-09-12 16:09:13 +02:00
///////////////////////////////
// Xerces platform initializer
/**
* Class to handle calls to XMLPlatformUtils::Initialize() and
* XMLPlatformUtils::Terminate().
*
* Without such a class, calls to Initialize() and Terminate() may be nested
* and cause evil consequences. Eg. A typical use of the old xerces_wrapper
* could have resulted in:
* <pre>
* // Construct two xerces_wrappers.
* XMLPlatformUtils::Initialize()
* XMLPlatformUtils::Initialize()
*
* // do stuff
*
* // Get rid of one of the xerces_wrappers
* XERCES_CPP_NAMESPACE::XMLPlatformUtils::Terminate()
*
* // do more stuff -- this is _after_ a call to Terminate()...
*
* XMLPlatformUtils::Terminate()
* </pre>
*/
class xerces_initializer
{
public:
xerces_initializer() { doInitialize(); }
~xerces_initializer() { doTerminate(); }
2003-09-12 16:09:13 +02:00
private:
void doInitialize();
void doTerminate();
static int count_;
}; // class xerces_initializer
} // namespace XercesImpl
template<class string_type, class string_adaptor_type = Arabica::default_string_adaptor<string_type> >
2003-09-12 16:09:13 +02:00
class xerces_wrapper : public SAX::basic_ProgressiveParser<string_type>
2002-06-21 13:16:28 +02:00
{
2003-09-12 16:09:13 +02:00
private:
2002-06-21 13:16:28 +02:00
typedef string_adaptor_type string_adaptorT;
2003-09-12 16:09:13 +02:00
protected:
typedef SAX::basic_XMLReader<string_type> base;
public:
typedef typename base::EntityResolverT EntityResolverT;
typedef typename base::DTDHandlerT DTDHandlerT;
typedef typename base::ContentHandlerT ContentHandlerT;
typedef typename base::InputSourceT InputSourceT;
typedef SAX::basic_LexicalHandler<string_type> LexicalHandlerT;
typedef SAX::basic_Locator<string_type> LocatorT;
typedef SAX::basic_Attributes<string_type> AttributesT;
typedef SAX::basic_DeclHandler<string_type> DeclHandlerT;
typedef SAX::XercesFeatureNames<string_type, string_adaptorT> featuresT;
2002-06-21 13:16:28 +02:00
xerces_wrapper();
2003-09-12 16:09:13 +02:00
virtual ~xerces_wrapper();
2002-06-21 13:16:28 +02:00
/////////////////////////////////////////////////
// Configuration
2003-09-12 16:09:13 +02:00
virtual bool getFeature(const string_type& name) const;
virtual void setFeature(const string_type& name, bool value);
2002-06-21 13:16:28 +02:00
/////////////////////////////////////////////////
// Event Handlers
2003-09-12 16:09:13 +02:00
virtual void setEntityResolver(EntityResolverT& resolver) { entityResolverAdaptor_.setEntityResolver(resolver); }
virtual EntityResolverT* getEntityResolver() const { return entityResolverAdaptor_.getEntityResolver(); }
virtual void setDTDHandler(DTDHandlerT& handler) { dtdHandlerAdaptor_.setDTDHandler(handler); }
virtual DTDHandlerT* getDTDHandler() const { return dtdHandlerAdaptor_.getDTDHandler(); }
virtual void setContentHandler(ContentHandlerT& handler) { contentHandlerAdaptor_.setContentHandler(handler); }
virtual ContentHandlerT* getContentHandler() const { return contentHandlerAdaptor_.getContentHandler(); }
virtual void setErrorHandler(ErrorHandler& handler) { errorHandlerAdaptor_.setErrorHandler(handler); }
virtual ErrorHandler* getErrorHandler() const { return errorHandlerAdaptor_.getErrorHandler(); }
2002-06-21 13:16:28 +02:00
//////////////////////////////////////////////////
// Parsing
2003-09-12 16:09:13 +02:00
virtual void parse(InputSourceT& input);
//////////////////////////////////////////////////
// Progressive Parsing
//////////////////////////////////////////////////
/** @name Progressive Parsing */
//@{
virtual bool parseFirst(const string_type& systemId, XMLPScanToken& toFill)
{
InputSourceT is(systemId);
return parseFirst(is, toFill);
}
virtual bool parseFirst(InputSourceT& input,
XMLPScanToken& toFill);
virtual bool parseNext(XMLPScanToken& token);
virtual void parseReset(XMLPScanToken& token);
//@}
2002-06-21 13:16:28 +02:00
protected:
2003-09-12 16:09:13 +02:00
virtual std::auto_ptr<typename base::PropertyBase> doGetProperty(const string_type& name);
virtual void doSetProperty(const string_type& name, std::auto_ptr<typename base::PropertyBase> value);
2002-06-21 13:16:28 +02:00
private:
///////////////////////////////
// String adaptor for XMLCh
// * For the null-terminated version, we convert the array of XMLCh to a
// null-terminated vector of wchar_t. We then pass &vector[0] to the
// parent method.
// * For the known length version, we convert the the array of XMLCh to a
// vector of wchar_t. We then pass &vector[0] and length to the parent
// method.
template<typename char_type>
class xerces_string_janitor
{
// Ordinarily you'd expect to be able to use Xerces' Array janitor class. However,
// Windows exes and dlls use seperate heaps, so you can't delete in one module that
// was allocated by another. It's a pita. The solution here is to use XMLString::release.
// Although this simply does a delete[], the deletion occurs in the Xerces DLL, so
// it will work correctly.
public:
xerces_string_janitor(char_type* ptr) : ptr_(ptr) { }
~xerces_string_janitor() { XERCES_CPP_NAMESPACE::XMLString::release(&ptr_); }
char_type const* const get() const { return ptr_; }
private:
char_type* ptr_;
xerces_string_janitor(const xerces_string_janitor&);
xerces_string_janitor& operator=(const xerces_string_janitor&) const;
}; // class xerces_string_janitor
class xerces_string_adaptor : public string_adaptorT
{
public:
2003-09-12 16:09:13 +02:00
typedef typename string_type::value_type value_type;
typedef string_adaptorT base;
2003-09-12 16:09:13 +02:00
typedef std::vector<wchar_t> wVector;
2003-09-14 22:47:43 +02:00
#ifndef ARABICA_NO_WCHAR_T
2003-09-12 16:09:13 +02:00
string_type makeStringT(const XMLCh* str) const
{
2003-09-14 22:47:43 +02:00
if(str)
2003-09-12 16:09:13 +02:00
{
wVector buffer;
std::insert_iterator<wVector> inserter(buffer, buffer.begin());
// We want the trailing 0 character.
*inserter = *str;
while (*str != 0) // str points to the character we've just copied
{
*++inserter = *++str;
}
return base::makeStringT(&buffer[0]);
}
else
{
return base::makeStringT("");
}
} // makeStringT
string_type makeStringT(const XMLCh* str, int length) const
{
if (str && length)
{
wVector buffer;
std::insert_iterator<wVector> inserter(buffer, buffer.begin());
// We don't want any trailing characters.
const XMLCh* end = str + length;
while (str < end)
{
*inserter++ = *str++;
}
return base::makeStringT(&buffer[0], length);
}
else
{
return base::makeStringT("");
}
} // makeStringT
2003-09-14 22:47:43 +02:00
#else
// alternative version for the wchar_t impaired
string_type makeStringT(const XMLCh* str) const
{
if(str)
{
2003-09-15 15:13:05 +02:00
xerces_string_janitor<char> cstr(XERCES_CPP_NAMESPACE::XMLString::transcode(str));
return base::makeStringT(cstr.get());
2003-09-14 22:47:43 +02:00
}
return base::makeStringT("");
} // makeStringT
string_type makeStringT(const XMLCh* str, int length) const
{
// this isn't pretty, but Xerces doesn't provide a transcode with takes
// a length
if(str && length)
{
std::vector<XMLCh> wv(length + 1);
std::copy(str, str+length, std::insert_iterator<std::vector<XMLCh> >(wv, wv.begin()));
wv.push_back(0);
return makeStringT(&wv[0]);
}
return base::makeStringT("");
} // makeStringT
#endif
2003-09-12 16:09:13 +02:00
XMLCh* asXMLChString(const string_type& s) const
2003-09-14 22:47:43 +02:00
{
std::string str = base::asStdString(s);
return XERCES_CPP_NAMESPACE::XMLString::transcode(str.c_str());
} // asXMLChString
2003-09-12 16:09:13 +02:00
}; // class xerces_string_adaptor
2002-06-21 13:16:28 +02:00
///////////////////////////////
// Adaptors
2003-09-12 16:09:13 +02:00
class LocatorAdaptor : public LocatorT
2002-06-21 13:16:28 +02:00
{
public:
LocatorAdaptor() : locator_(0) { }
LocatorAdaptor(const XERCES_CPP_NAMESPACE::Locator* const locator) : locator_(locator) { }
2002-06-21 13:16:28 +02:00
~LocatorAdaptor() { }
2003-09-12 16:09:13 +02:00
string_type getPublicId() const
2002-06-21 13:16:28 +02:00
{
if(!locator_)
2003-09-12 16:09:13 +02:00
return string_type();
2002-06-21 13:16:28 +02:00
return SA_.makeStringT(locator_->getPublicId());
} // getPublicId
2003-09-12 16:09:13 +02:00
string_type getSystemId() const
2002-06-21 13:16:28 +02:00
{
if(!locator_)
2003-09-12 16:09:13 +02:00
return string_type();
2002-06-21 13:16:28 +02:00
return SA_.makeStringT(locator_->getSystemId());
} // getSystemId
int getLineNumber() const
{
if(!locator_)
return -1;
return locator_->getLineNumber();
} // getLineNumber
int getColumnNumber() const
{
if(!locator_)
return -1;
return locator_->getColumnNumber();
} // getColumnNumber
void setLocator(const XERCES_CPP_NAMESPACE::Locator* const locator)
2002-06-21 13:16:28 +02:00
{
locator_ = locator;
} // setLocator
private:
const XERCES_CPP_NAMESPACE::Locator* locator_;
xerces_string_adaptor SA_;
2002-06-21 13:16:28 +02:00
}; // class LocatorAdaptor
2003-09-12 16:09:13 +02:00
class EntityResolverAdaptor : public XERCES_CPP_NAMESPACE::EntityResolver
{
public:
EntityResolverAdaptor() : entityResolverHandler_(0) { }
~EntityResolverAdaptor() { }
void setEntityResolver(EntityResolverT& handler)
{
entityResolverHandler_ = &handler;
}
EntityResolverT* getEntityResolver() const
{
return entityResolverHandler_;
}
virtual XERCES_CPP_NAMESPACE::InputSource* resolveEntity(const XMLCh* const publicId,
const XMLCh* const systemId)
{
InputSourceT source;
if(entityResolverHandler_)
{
source = entityResolverHandler_->resolveEntity(SA_.makeStringT(publicId),
SA_.makeStringT(systemId));
}
// If all of these are empty, the EntityResolver has requested that we
// use the default entity resolver.
if ((source.getByteStream() == 0) &&
(source.getPublicId().empty()) &&
(source.getSystemId().empty()))
{
// Xerces-C takes a NULL (0) return to mean "use the default entity
// resolver".
return 0;
}
else
{
return new InputSourceAdaptor(source);
}
}
private:
EntityResolverT* entityResolverHandler_;
xerces_string_adaptor SA_;
}; // class EntityResolverAdaptor
class DTDHandlerAdaptor : public XERCES_CPP_NAMESPACE::DTDHandler
2002-06-21 13:16:28 +02:00
{
public:
DTDHandlerAdaptor() : dtdHandler_(0) { }
~DTDHandlerAdaptor() { }
2003-09-12 16:09:13 +02:00
void setDTDHandler(DTDHandlerT& handler) { dtdHandler_ = &handler; }
DTDHandlerT* getDTDHandler() const { return dtdHandler_; }
2002-06-21 13:16:28 +02:00
virtual void notationDecl(const XMLCh* const name,
const XMLCh* const publicId,
const XMLCh* const systemId)
{
if(dtdHandler_)
dtdHandler_->notationDecl(SA_.makeStringT(name),
SA_.makeStringT(publicId),
SA_.makeStringT(systemId));
} // notationDecl
virtual void unparsedEntityDecl(const XMLCh* const name,
const XMLCh* const publicId,
const XMLCh* const systemId,
const XMLCh* const notationName)
{
if(dtdHandler_)
dtdHandler_->unparsedEntityDecl(SA_.makeStringT(name),
SA_.makeStringT(publicId),
SA_.makeStringT(systemId),
SA_.makeStringT(notationName));
} // unparsedEntityDecl
virtual void resetDocType()
{
// no op
} // resetDocType
private:
2003-09-12 16:09:13 +02:00
DTDHandlerT* dtdHandler_;
xerces_string_adaptor SA_;
2002-06-21 13:16:28 +02:00
}; // class DTDHandlerAdaptor
class ContentHandlerAdaptor : public XERCES_CPP_NAMESPACE::ContentHandler
2002-06-21 13:16:28 +02:00
{
public:
ContentHandlerAdaptor() : contentHandler_(0) { }
~ContentHandlerAdaptor() { }
2003-09-12 16:09:13 +02:00
void setContentHandler(ContentHandlerT& handler) { contentHandler_ = &handler; }
ContentHandlerT* getContentHandler() const { return contentHandler_; }
2002-06-21 13:16:28 +02:00
virtual void setDocumentLocator(const XERCES_CPP_NAMESPACE::Locator* const locator)
2002-06-21 13:16:28 +02:00
{
locator_.setLocator(locator);
if(contentHandler_)
contentHandler_->setDocumentLocator(locator_);
} // putDocumentLocation
virtual void startDocument()
{
if(contentHandler_)
contentHandler_->startDocument();
} // startDocument
virtual void endDocument()
{
if(contentHandler_)
contentHandler_->endDocument();
} // endDocument
virtual void startPrefixMapping(const XMLCh* const prefix, const XMLCh* const uri)
{
if(contentHandler_)
contentHandler_->startPrefixMapping(SA_.makeStringT(prefix), SA_.makeStringT(uri));
} // startPrefixMapping
virtual void endPrefixMapping(const XMLCh* const prefix)
{
if(contentHandler_)
contentHandler_->endPrefixMapping(SA_.makeStringT(prefix));
} // endPrefixMapping
virtual void startElement(const XMLCh* const namespaceUri,
const XMLCh* const localName,
const XMLCh* const rawName,
const XERCES_CPP_NAMESPACE::Attributes& attrs)
2002-06-21 13:16:28 +02:00
{
if(contentHandler_)
{
AttributesAdaptor attrAdaptor(attrs);
contentHandler_->startElement(SA_.makeStringT(namespaceUri),
SA_.makeStringT(localName),
SA_.makeStringT(rawName),
attrAdaptor);
} // if ...
} // startElement
virtual void endElement(const XMLCh* const namespaceUri,
const XMLCh* const localName,
const XMLCh* const rawName)
{
if(contentHandler_)
contentHandler_->endElement(SA_.makeStringT(namespaceUri),
SA_.makeStringT(localName),
SA_.makeStringT(rawName));
} // endElement
virtual void characters(const XMLCh* const chars, const unsigned int length)
{
if(contentHandler_)
contentHandler_->characters(SA_.makeStringT(chars, length));
} // characters
virtual void ignorableWhitespace(const XMLCh* const chars, const unsigned int length)
{
if(contentHandler_)
contentHandler_->ignorableWhitespace(SA_.makeStringT(chars, length));
} // ignorableWhitespace
virtual void processingInstruction(const XMLCh* const target,
const XMLCh* const data)
{
if(contentHandler_)
contentHandler_->processingInstruction(SA_.makeStringT(target),
SA_.makeStringT(data));
} // processingInstruction
virtual void skippedEntity(const XMLCh* const name)
{
if(contentHandler_)
contentHandler_->skippedEntity(SA_.makeStringT(name));
} // skippedEntity
private:
////////////////////////////////////////////////
// member varaibles
2003-09-12 16:09:13 +02:00
ContentHandlerT* contentHandler_;
2002-06-21 13:16:28 +02:00
LocatorAdaptor locator_;
xerces_string_adaptor SA_;
2002-06-21 13:16:28 +02:00
//////////////////////////////////////////////////////
// COM interface -> C++ interface adaptors
2003-09-12 16:09:13 +02:00
class AttributesAdaptor : public AttributesT
2002-06-21 13:16:28 +02:00
{
public:
AttributesAdaptor(const XERCES_CPP_NAMESPACE::Attributes& attrs) : attributes_(attrs) { }
2002-06-21 13:16:28 +02:00
~AttributesAdaptor() { }
/////////////////////////
// indexed access
virtual int getLength() const
{
return attributes_.getLength();
} // getLength
2003-09-12 16:09:13 +02:00
virtual string_type getURI(unsigned int index) const
2002-06-21 13:16:28 +02:00
{
return SA_.makeStringT(attributes_.getURI(index));
} // getURI
2003-09-12 16:09:13 +02:00
virtual string_type getLocalName(unsigned int index) const
2002-06-21 13:16:28 +02:00
{
return SA_.makeStringT(attributes_.getLocalName(index));
} // getLocalName
2003-09-12 16:09:13 +02:00
virtual string_type getQName(unsigned int index) const
2002-06-21 13:16:28 +02:00
{
return SA_.makeStringT(attributes_.getQName(index));
} // getQName
2003-09-12 16:09:13 +02:00
virtual string_type getType(unsigned int index) const
2002-06-21 13:16:28 +02:00
{
return SA_.makeStringT(attributes_.getType(index));
} // getType
2003-09-12 16:09:13 +02:00
virtual string_type getValue(unsigned int index) const
2002-06-21 13:16:28 +02:00
{
return SA_.makeStringT(attributes_.getValue(index));
} // getValue
/////////////////////////
// name based query
2003-09-12 16:09:13 +02:00
virtual int getIndex(const string_type& uri, const string_type& localName) const
2002-06-21 13:16:28 +02:00
{
xerces_string_janitor<XMLCh> wUri(SA_.asXMLChString(uri));
xerces_string_janitor<XMLCh> wLocalName(SA_.asXMLChString(localName));
return attributes_.getIndex(wUri.get(), wLocalName.get());
2002-06-21 13:16:28 +02:00
} // getIndex
2003-09-12 16:09:13 +02:00
virtual int getIndex(const string_type& qName) const
2002-06-21 13:16:28 +02:00
{
xerces_string_janitor<XMLCh> wQName(SA_.asXMLChString(qName));
return attributes_.getIndex(wQName.get());
2002-06-21 13:16:28 +02:00
} // getIndex
2003-09-12 16:09:13 +02:00
virtual string_type getType(const string_type& uri, const string_type& localName) const
2002-06-21 13:16:28 +02:00
{
xerces_string_janitor<XMLCh> wUri(SA_.asXMLChString(uri));
xerces_string_janitor<XMLCh> wLocalName(SA_.asXMLChString(localName));
return SA_.makeStringT(attributes_.getType(wUri.get(), wLocalName.get()));
2002-06-21 13:16:28 +02:00
} // getType
2003-09-12 16:09:13 +02:00
virtual string_type getType(const string_type& qName) const
2002-06-21 13:16:28 +02:00
{
xerces_string_janitor<XMLCh> wQName(SA_.asXMLChString(qName));
return SA_.makeStringT(attributes_.getType(wQName.get()));
2002-06-21 13:16:28 +02:00
} // getType
2003-09-12 16:09:13 +02:00
virtual string_type getValue(const string_type& uri, const string_type& localName) const
2002-06-21 13:16:28 +02:00
{
xerces_string_janitor<XMLCh> wUri(SA_.asXMLChString(uri));
xerces_string_janitor<XMLCh> wLocalName(SA_.asXMLChString(localName));
return SA_.makeStringT(attributes_.getValue(wUri.get(), wLocalName.get()));
2002-06-21 13:16:28 +02:00
} // getValue
2003-09-12 16:09:13 +02:00
virtual string_type getValue(const string_type& qname) const
2002-06-21 13:16:28 +02:00
{
xerces_string_janitor<XMLCh> wQName(SA_.asXMLChString(qname));
return SA_.makeStringT(attributes_.getValue(wQName.get()));
2002-06-21 13:16:28 +02:00
} // getValue
private:
const XERCES_CPP_NAMESPACE::Attributes& attributes_;
2003-09-12 16:09:13 +02:00
xerces_string_adaptor SA_;
2002-06-21 13:16:28 +02:00
AttributesAdaptor();
}; // class AttributesAdaptor
}; // class ContentHandlerAdaptor
class ErrorHandlerAdaptor : public XERCES_CPP_NAMESPACE::ErrorHandler
2002-06-21 13:16:28 +02:00
{
public:
ErrorHandlerAdaptor() : errorHandler_(0) { }
virtual ~ErrorHandlerAdaptor() { }
void setErrorHandler(SAX::ErrorHandler& handler) { errorHandler_ = &handler; }
SAX::ErrorHandler* getErrorHandler() const { return errorHandler_; }
virtual void warning(const XERCES_CPP_NAMESPACE::SAXParseException& exception)
2002-06-21 13:16:28 +02:00
{
handleError(exception, &SAX::ErrorHandler::warning);
2002-06-21 13:16:28 +02:00
} // warning
virtual void error(const XERCES_CPP_NAMESPACE::SAXParseException& exception)
2002-06-21 13:16:28 +02:00
{
handleError(exception, &SAX::ErrorHandler::error);
2002-06-21 13:16:28 +02:00
} // error
virtual void fatalError(const XERCES_CPP_NAMESPACE::SAXParseException& exception)
2002-06-21 13:16:28 +02:00
{
handleError(exception, &SAX::ErrorHandler::fatalError);
2002-06-21 13:16:28 +02:00
} // fatalError
virtual void resetErrors()
{
// no op
} // resetErrors
private:
typedef void(SAX::ErrorHandler::* ErrorFn)(const SAX::SAXParseException&);
2002-06-21 13:16:28 +02:00
void handleError(const XERCES_CPP_NAMESPACE::SAXParseException& exception, ErrorFn fn)
2002-06-21 13:16:28 +02:00
{
if(!errorHandler_)
return;
2003-09-12 16:09:13 +02:00
string_type errorMsg(SA_.makeStringT(exception.getMessage()));
string_type publicId(SA_.makeStringT(exception.getPublicId()));
string_type systemId(SA_.makeStringT(exception.getSystemId()));
SAX::SAXParseException sp(SA_.asStdString(errorMsg),
SA_.asStdString(publicId),
SA_.asStdString(systemId),
2002-06-21 13:16:28 +02:00
exception.getLineNumber(),
exception.getColumnNumber());
(errorHandler_->*fn)(sp);
} // handleError
SAX::ErrorHandler* errorHandler_;
xerces_string_adaptor SA_;
2002-06-21 13:16:28 +02:00
}; // class ErrorHandlerAdaptor
class LexicalHandlerAdaptor : public XERCES_CPP_NAMESPACE::LexicalHandler
2002-06-21 13:16:28 +02:00
{
public:
LexicalHandlerAdaptor() : lexicalHandler_(0) { }
virtual ~LexicalHandlerAdaptor() { }
2003-09-12 16:09:13 +02:00
void setLexicalHandler(LexicalHandlerT& handler) { lexicalHandler_ = &handler; }
LexicalHandlerT* getLexicalHandler() const { return lexicalHandler_; }
2002-06-21 13:16:28 +02:00
virtual void startDTD(const XMLCh* const name,
const XMLCh* const publicId,
const XMLCh* const systemId)
{
if(lexicalHandler_)
lexicalHandler_->startDTD(SA_.makeStringT(name),
SA_.makeStringT(publicId),
SA_.makeStringT(systemId));
} // startDTD
virtual void endDTD()
{
if(lexicalHandler_)
lexicalHandler_->endDTD();
} // endDTD
virtual void startEntity(const XMLCh* const name)
{
if(lexicalHandler_)
lexicalHandler_->startEntity(SA_.makeStringT(name));
} // startEntity
virtual void endEntity(const XMLCh* const name)
{
if(lexicalHandler_)
lexicalHandler_->endEntity(SA_.makeStringT(name));
} // endEntity
virtual void startCDATA()
{
if(lexicalHandler_)
lexicalHandler_->startCDATA();
} // startCDATA
virtual void endCDATA()
{
if(lexicalHandler_)
lexicalHandler_->endCDATA();
} // endCDATA
virtual void comment(const XMLCh* const chars, const unsigned int length)
{
if(lexicalHandler_)
lexicalHandler_->comment(SA_.makeStringT(chars, length));
} // comment
private:
2003-09-12 16:09:13 +02:00
LexicalHandlerT* lexicalHandler_;
xerces_string_adaptor SA_;
2002-06-21 13:16:28 +02:00
}; // class LexicalHandlerAdaptor
class DeclHandlerAdaptor : public XERCES_CPP_NAMESPACE::DeclHandler
2002-06-21 13:16:28 +02:00
{
public:
DeclHandlerAdaptor() : declHandler_(0) { }
virtual ~DeclHandlerAdaptor() { }
2003-09-12 16:09:13 +02:00
void setDeclHandler(DeclHandlerT& handler) { declHandler_ = &handler; }
DeclHandlerT* getDeclHandler() const { return declHandler_; }
2002-06-21 13:16:28 +02:00
virtual void elementDecl(const XMLCh* const name,
const XMLCh* const model)
{
if(declHandler_)
declHandler_->elementDecl(SA_.makeStringT(name),
SA_.makeStringT(model));
} // elementDecl
virtual void attributeDecl(const XMLCh* const elementName,
const XMLCh* const attributeName,
const XMLCh* const type,
const XMLCh* const valueDefault,
const XMLCh* const value)
{
if(declHandler_)
2003-09-12 16:09:13 +02:00
{
const XMLCh* tmpValueDefault = valueDefault;
if (tmpValueDefault == XERCES_CPP_NAMESPACE::XMLUni::fgNullString)
tmpValueDefault = 0;
2002-06-21 13:16:28 +02:00
declHandler_->attributeDecl(SA_.makeStringT(elementName),
SA_.makeStringT(attributeName),
SA_.makeStringT(type),
2003-09-12 16:09:13 +02:00
SA_.makeStringT(tmpValueDefault),
2002-06-21 13:16:28 +02:00
SA_.makeStringT(value));
2003-09-12 16:09:13 +02:00
}
2002-06-21 13:16:28 +02:00
} // attributeDecl
virtual void internalEntityDecl(const XMLCh* const name,
const XMLCh* const value)
{
if(declHandler_)
declHandler_->internalEntityDecl(SA_.makeStringT(name),
SA_.makeStringT(value));
} // internalEntityDecl
virtual void externalEntityDecl(const XMLCh* const name,
const XMLCh* const publicId,
const XMLCh* const systemId)
{
if(declHandler_)
declHandler_->externalEntityDecl(SA_.makeStringT(name),
SA_.makeStringT(publicId),
SA_.makeStringT(systemId));
} // externalEntityDecl
private:
2003-09-12 16:09:13 +02:00
DeclHandlerT* declHandler_;
xerces_string_adaptor SA_;
2002-06-21 13:16:28 +02:00
}; // class DeclHandlerAdaptor
class IStreamAdaptor : public XERCES_CPP_NAMESPACE::BinInputStream
2002-06-21 13:16:28 +02:00
{
public:
2003-09-12 16:09:13 +02:00
IStreamAdaptor(IStreamHandle istream)
: istream_(istream),
curPos_(0)
{ }
2002-06-21 13:16:28 +02:00
virtual ~IStreamAdaptor() { }
virtual unsigned int curPos() const
{
return curPos_;
} // curPos
2003-09-12 16:09:13 +02:00
virtual unsigned int readBytes(XMLByte* const toFill,
const unsigned int maxToRead)
2002-06-21 13:16:28 +02:00
{
2003-09-12 16:09:13 +02:00
istream_.get()->read(reinterpret_cast<char*>(toFill), maxToRead);
curPos_ += istream_.get()->gcount();
return istream_.get()->gcount();
2002-06-21 13:16:28 +02:00
} // readBytes
private:
2003-09-12 16:09:13 +02:00
IStreamHandle istream_;
2002-06-21 13:16:28 +02:00
unsigned int curPos_;
}; // IStreamAdaptor
class InputSourceAdaptor : public XERCES_CPP_NAMESPACE::InputSource
2002-06-21 13:16:28 +02:00
{
public:
2003-09-12 16:09:13 +02:00
InputSourceAdaptor(const InputSourceT& source)
: inputSource_(source)
2002-06-21 13:16:28 +02:00
{
xerces_string_janitor<XMLCh> wSystemId(SA_.asXMLChString(source.getSystemId()));
xerces_string_janitor<XMLCh> wPublicId(SA_.asXMLChString(source.getPublicId()));
setSystemId(wSystemId.get());
setPublicId(wPublicId.get());
2002-06-21 13:16:28 +02:00
} // InputSourceAdaptor
virtual ~InputSourceAdaptor() { }
virtual XERCES_CPP_NAMESPACE::BinInputStream* makeStream() const
2002-06-21 13:16:28 +02:00
{
2003-09-12 16:09:13 +02:00
return new IStreamAdaptor(inputSource_.getByteStreamHandle());
2002-06-21 13:16:28 +02:00
} // makeStream
private:
2003-09-12 16:09:13 +02:00
// This is a local copy, so we do not rely on someone else keeping
// their InputSourceT around for us.
InputSourceT inputSource_;
xerces_string_adaptor SA_;
2003-09-12 16:09:13 +02:00
}; // class InputSourceAdaptor
2002-06-21 13:16:28 +02:00
2003-09-12 16:09:13 +02:00
class XercesXMLPScanToken : public ::SAX::XMLPScanTokenParserImpl
{
public:
XERCES_CPP_NAMESPACE::XMLPScanToken token_;
};
2002-06-21 13:16:28 +02:00
/////////////////////////////////////////////
// Member variables
2003-09-12 16:09:13 +02:00
std::auto_ptr<XercesImpl::xerces_initializer> initializer_;
XERCES_CPP_NAMESPACE::SAX2XMLReader* xerces_;
2002-06-21 13:16:28 +02:00
ContentHandlerAdaptor contentHandlerAdaptor_;
2003-09-12 16:09:13 +02:00
EntityResolverAdaptor entityResolverAdaptor_;
2002-06-21 13:16:28 +02:00
DTDHandlerAdaptor dtdHandlerAdaptor_;
ErrorHandlerAdaptor errorHandlerAdaptor_;
LexicalHandlerAdaptor lexicalHandlerAdaptor_;
DeclHandlerAdaptor declHandlerAdaptor_;
xerces_string_adaptor SA_;
2003-09-12 16:09:13 +02:00
SAX::XercesPropertyNames<string_type, string_adaptorT> properties_;
// Property values to return by reference
string_type externalSchemaLocation_;
string_type externalNoNamespaceSchemaLocation_;
2002-06-21 13:16:28 +02:00
}; // class xerces_wrapper
2003-09-12 16:09:13 +02:00
template<class string_type, class string_adaptorT>
xerces_wrapper<string_type, string_adaptorT>::xerces_wrapper()
2002-06-21 13:16:28 +02:00
{
try
{
2003-09-12 16:09:13 +02:00
std::auto_ptr<XercesImpl::xerces_initializer> init(new XercesImpl::xerces_initializer());
initializer_ = init;
2002-06-21 13:16:28 +02:00
}
catch(const XERCES_CPP_NAMESPACE::XMLException& toCatch)
2002-06-21 13:16:28 +02:00
{
2003-09-12 16:09:13 +02:00
string_type s = SA_.makeStringT(toCatch.getMessage());
2002-06-21 13:16:28 +02:00
throw SAX::SAXException(SA_.asStdString(s));
} // catch
xerces_ = XERCES_CPP_NAMESPACE::XMLReaderFactory::createXMLReader();
2002-06-21 13:16:28 +02:00
xerces_->setContentHandler(&contentHandlerAdaptor_);
2003-09-12 16:09:13 +02:00
xerces_->setEntityResolver(&entityResolverAdaptor_);
2002-06-21 13:16:28 +02:00
xerces_->setDTDHandler(&dtdHandlerAdaptor_);
xerces_->setErrorHandler(&errorHandlerAdaptor_);
xerces_->setLexicalHandler(&lexicalHandlerAdaptor_);
xerces_->setDeclarationHandler(&declHandlerAdaptor_);
} // xerces_wrapper
2003-09-12 16:09:13 +02:00
template<class string_type, class string_adaptorT>
xerces_wrapper<string_type, string_adaptorT>::~xerces_wrapper()
2002-06-21 13:16:28 +02:00
{
delete xerces_;
} // ~xerces_wrapper
2003-09-12 16:09:13 +02:00
template<class string_type, class string_adaptorT>
bool xerces_wrapper<string_type, string_adaptorT>::getFeature(const string_type& name) const
2002-06-21 13:16:28 +02:00
{
try
{
xerces_string_janitor<XMLCh> wName(SA_.asXMLChString(name));
return xerces_->getFeature(wName.get());
2002-06-21 13:16:28 +02:00
} // try
catch(XERCES_CPP_NAMESPACE::SAXNotSupportedException& e)
2002-06-21 13:16:28 +02:00
{
throw SAX::SAXNotSupportedException(SA_.makeStringT(e.getMessage()));
} // catch(SAXNotSupportedException& e)
catch(XERCES_CPP_NAMESPACE::SAXNotRecognizedException& e)
2002-06-21 13:16:28 +02:00
{
throw SAX::SAXNotRecognizedException(SA_.makeStringT(e.getMessage()));
} // catch(SAXNotRecognizedException& e)
} // getFeature
2003-09-12 16:09:13 +02:00
template<class string_type, class string_adaptorT>
void xerces_wrapper<string_type, string_adaptorT>::setFeature(const string_type& name, bool value)
2002-06-21 13:16:28 +02:00
{
try
{
xerces_string_janitor<XMLCh> wName(SA_.asXMLChString(name));
xerces_->setFeature(wName.get(), value);
2002-06-21 13:16:28 +02:00
} // try
catch(XERCES_CPP_NAMESPACE::SAXNotSupportedException& e)
2002-06-21 13:16:28 +02:00
{
throw SAX::SAXNotSupportedException(SA_.makeStringT(e.getMessage()));
} // catch(SAXNotSupportedException& e)
catch(XERCES_CPP_NAMESPACE::SAXNotRecognizedException& e)
2002-06-21 13:16:28 +02:00
{
throw SAX::SAXNotRecognizedException(SA_.makeStringT(e.getMessage()));
} // catch(SAXNotRecognizedException& e)
} // setFeature
2003-09-12 16:09:13 +02:00
template<class string_type, class string_adaptorT>
2003-09-15 18:04:37 +02:00
#ifndef ARABICA_VS6_WORKAROUND
2003-09-12 16:09:13 +02:00
std::auto_ptr<typename SAX::basic_XMLReader<string_type>::PropertyBase> xerces_wrapper<string_type, string_adaptorT>::doGetProperty(const string_type& name)
2003-09-15 18:04:37 +02:00
#else
std::auto_ptr<SAX::basic_XMLReader<string_type>::PropertyBase> xerces_wrapper<string_type, string_adaptorT>::doGetProperty(const string_type& name)
#endif
2002-06-21 13:16:28 +02:00
{
if(name == properties_.lexicalHandler)
{
2003-09-12 16:09:13 +02:00
SAX::basic_XMLReader<string_type>::Property<LexicalHandlerT *> *prop = new SAX::basic_XMLReader<string_type>::Property<LexicalHandlerT *>(lexicalHandlerAdaptor_.getLexicalHandler());
2003-09-15 18:04:37 +02:00
#ifndef ARABICA_VS6_WORKAROUND
2003-09-12 16:09:13 +02:00
return std::auto_ptr<typename base::PropertyBase>(prop);
2003-09-15 18:04:37 +02:00
#else
return std::auto_ptr<base::PropertyBase>(prop);
#endif
2002-06-21 13:16:28 +02:00
}
if(name == properties_.declHandler)
{
2003-09-12 16:09:13 +02:00
SAX::basic_XMLReader<string_type>::Property<DeclHandlerT*>* prop = new SAX::basic_XMLReader<string_type>::Property<DeclHandlerT*>(declHandlerAdaptor_.getDeclHandler());
2003-09-15 18:04:37 +02:00
#ifndef ARABICA_VS6_WORKAROUND
2003-09-12 16:09:13 +02:00
return std::auto_ptr<typename base::PropertyBase>(prop);
2003-09-15 18:04:37 +02:00
#else
return std::auto_ptr<base::PropertyBase>(prop);
#endif
2003-09-12 16:09:13 +02:00
}
if (name == properties_.externalSchemaLocation)
{
typedef SAX::basic_XMLReader<string_type>::Property<string_type&> StringPropertyType;
XMLCh* xercesExternalSchemaLocation =
static_cast<XMLCh*>(xerces_->getProperty(
XERCES_CPP_NAMESPACE::XMLUni::fgXercesSchemaExternalSchemaLocation));
externalSchemaLocation_ = SA_.makeStringT(xercesExternalSchemaLocation);
2003-09-15 18:04:37 +02:00
#ifndef ARABICA_VS6_WORKAROUND
std::auto_ptr<typename base::PropertyBase> toReturn(new StringPropertyType(externalSchemaLocation_));
#else
std::auto_ptr<base::PropertyBase> toReturn(new StringPropertyType(externalSchemaLocation_));
#endif
2003-09-12 16:09:13 +02:00
#ifdef SAXXERCES_DEBUG
std::cerr << "Returning " << typeid(toReturn)
<< "(*(" << typeid(*toReturn.get()) << ")"
<< toReturn.get() << ")"
<< " containing value [" << externalSchemaLocation_ << "]"
<< std::endl;
#endif
return toReturn;
}
if (name == properties_.externalNoNamespaceSchemaLocation)
{
typedef SAX::basic_XMLReader<string_type>::Property<string_type&> StringPropertyType;
XMLCh* xercesExternalNoNamespaceSchemaLocation =
static_cast<XMLCh*>(xerces_->getProperty(
XERCES_CPP_NAMESPACE::XMLUni::fgXercesSchemaExternalNoNameSpaceSchemaLocation));
2003-09-15 18:04:37 +02:00
externalNoNamespaceSchemaLocation_ = SA_.makeStringT(xercesExternalNoNamespaceSchemaLocation);
#ifndef ARABICA_VS6_WORKAROUND
return std::auto_ptr<typename base::PropertyBase>(new StringPropertyType(externalNoNamespaceSchemaLocation_));
#else
return std::auto_ptr<base::PropertyBase>(new StringPropertyType(externalNoNamespaceSchemaLocation_));
#endif
2002-06-21 13:16:28 +02:00
}
throw SAX::SAXNotRecognizedException("Property not recognized ");
} // doGetProperty
2003-09-12 16:09:13 +02:00
template<class string_type, class string_adaptorT>
2003-09-15 18:04:37 +02:00
#ifndef ARABICA_VS6_WORKAROUND
2003-09-12 16:09:13 +02:00
void xerces_wrapper<string_type, string_adaptorT>::doSetProperty(const string_type& name, std::auto_ptr<typename base::PropertyBase> value)
2003-09-15 18:04:37 +02:00
#else
void xerces_wrapper<string_type, string_adaptorT>::doSetProperty(const string_type& name, std::auto_ptr<base::PropertyBase> value)
#endif
2002-06-21 13:16:28 +02:00
{
if(name == properties_.lexicalHandler)
{
2003-09-12 16:09:13 +02:00
SAX::basic_XMLReader<string_type>::Property<LexicalHandlerT&>* prop = dynamic_cast<SAX::basic_XMLReader<string_type>::Property<LexicalHandlerT&>*>(value.get());
2002-06-21 13:16:28 +02:00
if(!prop)
2003-09-12 16:09:13 +02:00
{
throw SAXNotSupportedException("Property LexicalHandler is wrong type, should be SAX::LexicalHandler&");
}
2002-06-21 13:16:28 +02:00
lexicalHandlerAdaptor_.setLexicalHandler(prop->get());
return;
} // if ...
2003-09-12 16:09:13 +02:00
2002-06-21 13:16:28 +02:00
if(name == properties_.declHandler)
{
2003-09-12 16:09:13 +02:00
SAX::basic_XMLReader<string_type>::Property<DeclHandlerT&>* prop = dynamic_cast<SAX::basic_XMLReader<string_type>::Property<DeclHandlerT&>*>(value.get());
2002-06-21 13:16:28 +02:00
if(!prop)
2003-09-12 16:09:13 +02:00
{
throw SAXNotSupportedException("Property DeclHandler is wrong type, should be SAX::DeclHandler&");
}
2002-06-21 13:16:28 +02:00
declHandlerAdaptor_.setDeclHandler(prop->get());
return;
} // if ...
2003-09-12 16:09:13 +02:00
if (name == properties_.externalSchemaLocation)
{
typename base::PropertyBase* propBase = value.get();
#ifdef SAXXERCES_DEBUG
std::cerr << "doSetProperty(externalSchemaLocation, &("
<< typeid(*propBase) << "))" << std::endl;
#endif
typedef base::Property<string_type&> propertyType;
propertyType* prop = dynamic_cast<propertyType*>(propBase);
#ifdef SAXXERCES_DEBUG
std::cerr << " Extracted property to " << typeid(prop)
<< "(" << prop << ")" << std::endl;
#endif
if (prop)
{
externalSchemaLocation_ = prop->get();
#ifdef SAXXERCES_DEBUG
std::cerr << " Setting property to " << externalSchemaLocation_ << std::endl;
#endif
xerces_string_janitor<XMLCh> toDelete(SA_.asXMLChString(externalSchemaLocation_));
xerces_->setProperty(XERCES_CPP_NAMESPACE::XMLUni::fgXercesSchemaExternalSchemaLocation, const_cast<XMLCh*>(toDelete.get()));
2003-09-12 16:09:13 +02:00
}
else
{
throw SAXNotSupportedException("Property ExternalShemaLocation is wrong type, should be string_type");
}
return;
}
if (name == properties_.externalNoNamespaceSchemaLocation)
{
typename base::PropertyBase* propBase = value.get();
typedef base::Property<string_type&> propertyType;
#ifdef SAXXERCES_DEBUG
std::cerr << "doSetProperty(externalNoNamespaceSchemaLocation, &("
<< typeid(*propBase) << "))" << std::endl;
#endif
propertyType* prop = dynamic_cast<propertyType*>(propBase);
#ifdef SAXXERCES_DEBUG
std::cerr << " Extracted property to " << typeid(prop)
<< "(" << prop << ")" << std::endl;
#endif
2003-09-12 16:09:13 +02:00
if (prop)
{
externalNoNamespaceSchemaLocation_ = prop->get();
#ifdef SAXXERCES_DEBUG
std::cerr << " Setting property to " << externalNoNamespaceSchemaLocation_ << std::endl;
#endif
xerces_string_janitor<XMLCh> toDelete(SA_.asXMLChString(externalNoNamespaceSchemaLocation_));
xerces_->setProperty(XERCES_CPP_NAMESPACE::XMLUni::fgXercesSchemaExternalNoNameSpaceSchemaLocation, const_cast<XMLCh*>(toDelete.get()));
2003-09-12 16:09:13 +02:00
}
else
{
throw SAXNotSupportedException("Property ExternalNoNamespaceSchemaLocation is wrong type, should be string_type");
}
return;
}
throw SAX::SAXNotRecognizedException("Property not recognized ");
}
2003-09-12 16:09:13 +02:00
template<class string_type, class string_adaptorT>
void xerces_wrapper<string_type, string_adaptorT>::parse(InputSourceT& source)
2002-06-21 13:16:28 +02:00
{
// if no stream is open, let Xerces deal with it
if(source.getByteStream() == 0)
xerces_->parse(SA_.asStdString(source.getSystemId()).c_str());
else
{
// we have to wrap everything up in a Xerces friendly way
InputSourceAdaptor isAdaptor(source);
xerces_->parse(isAdaptor);
} // if ...
} // parse
2003-09-12 16:09:13 +02:00
template<class string_type, class string_adaptorT>
bool xerces_wrapper<string_type,
string_adaptorT>::parseFirst(InputSourceT& input,
XMLPScanToken& toFill)
{
std::auto_ptr<XercesXMLPScanToken> newToken(new XercesXMLPScanToken);
// To store the result from Xerces parseFirst().
bool result = false;
if (input.getByteStream() == 0)
{
// We can just pass the systemID to parseFirst and let Xerces open the
// stream.
const char* systemID = SA_.asStdString(input.getSystemId()).c_str();
result = xerces_->parseFirst(systemID, newToken->token_);
}
else
{
// We need to wrap input in an InputSourceAdaptor.
// isAdaptor can be a local variable because Xerces has to open any streams
// within the parseFirst() call, so it should not need the
// InputSourceAdaptor to hang around.
InputSourceAdaptor isAdaptor(input);
result = xerces_->parseFirst(isAdaptor, newToken->token_);
}
if (result) {
// We need to explicitly convert to auto_ptr<base class>.
2003-09-15 18:04:37 +02:00
std::auto_ptr<XMLPScanTokenParserImpl> toSet(newToken.release());
2003-09-12 16:09:13 +02:00
toFill.setParserData(toSet);
}
return result;
} // parseFirst
template<class string_type, class string_adaptorT>
bool xerces_wrapper<string_type, string_adaptorT>::parseNext(XMLPScanToken& token)
{
// Extract the XercesXMLPScanToken from within token.
XercesXMLPScanToken* xercesToken =
dynamic_cast<XercesXMLPScanToken*>(token.parserImpl());
if (xercesToken == 0)
{
// If it failed to cast, we can simply refuse to parse, because this call
// clearly isn't following a successful parseFirst().
return false;
}
else
{
// Otherwise, just pass the token to Xerces.
return xerces_->parseNext(xercesToken->token_);
}
} // parseNext
template<class string_type, class string_adaptorT>
void xerces_wrapper<string_type, string_adaptorT>::parseReset(XMLPScanToken& token)
{
// Extract the XercesXMLPScanToken from within token.
XercesXMLPScanToken* xercesToken =
dynamic_cast<XercesXMLPScanToken*>(token.parserImpl());
// If it failed to cast, we can simply ignore it, because this call clearly
// isn't following a successful parseFirst().
if (xercesToken != 0)
{
xerces_->parseReset(xercesToken->token_);
}
} // parseReset
2002-06-21 13:16:28 +02:00
} // namespace SAX
#endif
// end of file