mirror of
https://github.com/jezhiggins/arabica
synced 2024-12-26 21:58:39 +01:00
6bf75264de
For nearly everyone, their use can be replaced by either setLexicalHandler or setDeclHandler. For the particular case of the Xerces extended properties I'll loop back round and add specific member methods for those.
900 lines
34 KiB
C++
900 lines
34 KiB
C++
#ifndef ARABICA_SAX_LIBXML2_H
|
|
#define ARABICA_SAX_LIBXML2_H
|
|
////////////////////////////////////////////////////////////////
|
|
// A SAX2 Wrapper for libxml2
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
#include <SAX/ArabicaConfig.hpp>
|
|
#include <SAX/XMLReader.hpp>
|
|
#include <SAX/SAXParseException.hpp>
|
|
#include <SAX/InputSource.hpp>
|
|
#include <SAX/SAXNotSupportedException.hpp>
|
|
#include <SAX/SAXNotRecognizedException.hpp>
|
|
#include <libxml/parser.h>
|
|
|
|
#include <string>
|
|
#include <cstdarg>
|
|
#include <typeinfo>
|
|
|
|
#include <SAX/helpers/FeatureNames.hpp>
|
|
#include <SAX/helpers/NamespaceSupport.hpp>
|
|
#include <SAX/helpers/AttributeDefaults.hpp>
|
|
#include <SAX/helpers/AttributeTypes.hpp>
|
|
#include <SAX/helpers/InputSourceResolver.hpp>
|
|
#include <SAX/helpers/AttributesImpl.hpp>
|
|
#include <Arabica/getparam.hpp>
|
|
|
|
namespace Arabica
|
|
{
|
|
namespace SAX
|
|
{
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
// the callback functions for libxml
|
|
namespace libxml2_wrapper_impl_tiddle
|
|
{
|
|
|
|
extern "C"
|
|
{
|
|
|
|
void lwit_startDocument(void* user_data);
|
|
void lwit_endDocument(void* user_data);
|
|
void lwit_startElement(void *user_data, const xmlChar* name, const xmlChar** attrs);
|
|
void lwit_endElement(void *user_data, const xmlChar* name);
|
|
void lwit_characters(void* user_data, const xmlChar* ch, int len);
|
|
void lwit_cdata(void* user_data, const xmlChar* ch, int len);
|
|
void lwit_ignorableWhitespace(void *user_data, const xmlChar* ch, int len);
|
|
void lwit_processingInstruction(void *user_data, const xmlChar* target, const xmlChar* data);
|
|
void lwit_comment(void *user_data, const xmlChar* comment);
|
|
void lwit_warning(void *user_data, const char* fmt, ...);
|
|
void lwit_error(void* user_data, const char* fmt, ...);
|
|
void lwit_fatalError(void* user_data, const char* fmt, ...);
|
|
void lwit_locator(void* user_data, xmlSAXLocatorPtr locator);
|
|
void lwit_notationDecl(void* user_data, const xmlChar *name, const xmlChar *publicId, const xmlChar *systemId);
|
|
void lwit_unparsedEntityDecl(void* user_data,
|
|
const xmlChar *name, const xmlChar *publicId,
|
|
const xmlChar *systemId, const xmlChar *notationName);
|
|
void lwit_elementDecl(void* user_date, const xmlChar *name, int type, xmlElementContentPtr content);
|
|
void lwit_attributeDecl(void *user_data, const xmlChar *elem, const xmlChar *fullname, int type, int def, const xmlChar *defaultValue, xmlEnumerationPtr tree);
|
|
void lwit_entityDecl(void* user_data, const xmlChar *name, int type, const xmlChar *publicId, const xmlChar *systemId, xmlChar *content);
|
|
void lwit_setFeature(xmlParserCtxtPtr context, const char* name, bool value);
|
|
bool lwit_getFeature(xmlParserCtxtPtr context, const char* name);
|
|
xmlEntityPtr lwit_getEntity(void* user_data, const xmlChar* name);
|
|
xmlParserInputPtr lwit_resolveEntity(void* user_data, const xmlChar* publicId, const xmlChar* systemId);
|
|
xmlSAXHandler* lwit_SaxHandler();
|
|
|
|
class libxml2_base
|
|
{
|
|
protected:
|
|
virtual ~libxml2_base() { }
|
|
|
|
private:
|
|
virtual void SAXstartDocument() = 0;
|
|
virtual void SAXendDocument() = 0;
|
|
virtual void SAXlocator(xmlSAXLocatorPtr locator) = 0;
|
|
virtual void SAXcharacters(const xmlChar* ch, int len) = 0;
|
|
virtual void SAXcdata(const xmlChar* ch, int len) = 0;
|
|
virtual void SAXignorableWhitespace(const xmlChar* ch, int len) = 0;
|
|
virtual void SAXwarning(const std::string& warning) = 0;
|
|
virtual void SAXerror(const std::string& error) = 0;
|
|
virtual void SAXfatalError(const std::string& fatal) = 0;
|
|
virtual void SAXprocessingInstruction(const xmlChar* target, const xmlChar* data) = 0;
|
|
virtual void SAXcomment(const xmlChar* comment) = 0;
|
|
virtual void SAXstartElement(const xmlChar* name, const xmlChar** attrs) = 0;
|
|
virtual void SAXendElement(const xmlChar* name) = 0;
|
|
virtual void SAXnotationDecl(const xmlChar *name, const xmlChar *publicId, const xmlChar *systemId) = 0;
|
|
virtual void SAXunparsedEntityDecl(const xmlChar *name, const xmlChar *publicId, const xmlChar *systemId, const xmlChar *notationName) = 0;
|
|
virtual void SAXelementDecl(const xmlChar* name, int type, xmlElementContentPtr content) = 0;
|
|
virtual void SAXattributeDecl(const xmlChar *elem, const xmlChar *fullname, int type, int def, const xmlChar *defaultValue, xmlEnumerationPtr tree) = 0;
|
|
virtual void SAXentityDecl(const xmlChar *name, int type, const xmlChar *publicId, const xmlChar *systemId, xmlChar *content) = 0;
|
|
virtual xmlParserInputPtr SAXresolveEntity(const xmlChar* publicId, const xmlChar* systemId) = 0;
|
|
virtual xmlParserCtxtPtr parserContext() = 0;
|
|
|
|
virtual void SAXstartCdataSection() = 0;
|
|
virtual void SAXendCdataSection() = 0;
|
|
|
|
friend void lwit_startDocument(void* user_data);
|
|
friend void lwit_endDocument(void* user_data);
|
|
friend void lwit_characters(void *user_data, const xmlChar* ch, int len);
|
|
friend void lwit_cdata(void *user_data, const xmlChar* ch, int len);
|
|
friend void lwit_ignorableWhitespace(void *user_data, const xmlChar* ch, int len);
|
|
friend void lwit_locator(void* user_data, xmlSAXLocatorPtr locator);
|
|
friend void lwit_warning(void *user_data, const char* fmt, ...);
|
|
friend void lwit_error(void* user_data, const char* fmt, ...);
|
|
friend void lwit_fatalError(void* user_data, const char* fmt, ...);
|
|
friend void lwit_processingInstruction(void *user_data, const xmlChar* target, const xmlChar* data);
|
|
friend void lwit_comment(void *user_data, const xmlChar* comment);
|
|
friend void lwit_startElement(void *user_data, const xmlChar* name, const xmlChar** attrs);
|
|
friend void lwit_endElement(void* user_data, const xmlChar* name);
|
|
friend void lwit_notationDecl(void* user_data, const xmlChar *name, const xmlChar *publicId, const xmlChar *systemId);
|
|
friend void lwit_unparsedEntityDecl(void* user_data, const xmlChar *name, const xmlChar *publicId, const xmlChar *systemId, const xmlChar *notationName);
|
|
friend void lwit_elementDecl(void* user_data, const xmlChar *name, int type, xmlElementContentPtr content);
|
|
friend void lwit_attributeDecl(void* user_data, const xmlChar *elem, const xmlChar *fullname, int type, int def, const xmlChar *defaultValue, xmlEnumerationPtr tree);
|
|
friend void lwit_entityDecl(void* user_data, const xmlChar *name, int type, const xmlChar *publicId, const xmlChar *systemId, xmlChar *content);
|
|
friend xmlEntityPtr lwit_getEntity(void* user_data, const xmlChar* name);
|
|
friend xmlParserInputPtr lwit_resolveEntity(void* user_data, const xmlChar* publicId, const xmlChar* systemId);
|
|
}; // class libxml2_base
|
|
|
|
} // extern "C"
|
|
|
|
} // namespace libxml2_wrapper_impl_tiddle
|
|
|
|
template<class string_type,
|
|
class T0 = Arabica::nil_t,
|
|
class T1 = Arabica::nil_t>
|
|
class libxml2_wrapper :
|
|
public SAX::XMLReaderInterface<string_type,
|
|
typename Arabica::get_string_adaptor<string_type, T0, T1>::type>,
|
|
public SAX::Locator<string_type, typename Arabica::get_string_adaptor<string_type, T0, T1>::type>,
|
|
protected libxml2_wrapper_impl_tiddle::libxml2_base
|
|
{
|
|
public:
|
|
typedef SAX::XMLReaderInterface<string_type,
|
|
typename Arabica::get_string_adaptor<string_type, T0, T1>::type> XMLReaderT;
|
|
typedef typename XMLReaderT::string_adaptor string_adaptor;
|
|
typedef SAX::EntityResolver<string_type, string_adaptor> entityResolverT;
|
|
typedef SAX::DTDHandler<string_type, string_adaptor> dtdHandlerT;
|
|
typedef SAX::ContentHandler<string_type, string_adaptor> contentHandlerT;
|
|
typedef SAX::Attributes<string_type, string_adaptor> attributesT;
|
|
typedef SAX::AttributeType<string_type, string_adaptor> attributeTypeT;
|
|
typedef SAX::DeclHandler<string_type, string_adaptor> declHandlerT;
|
|
typedef SAX::LexicalHandler<string_type, string_adaptor> lexicalHandlerT;
|
|
typedef SAX::InputSource<string_type, string_adaptor> inputSourceT;
|
|
typedef SAX::Locator<string_type, string_adaptor> locatorT;
|
|
typedef SAX::NamespaceSupport<string_type, string_adaptor> namespaceSupportT;
|
|
typedef SAX::ErrorHandler<string_type, string_adaptor> errorHandlerT;
|
|
typedef SAX::SAXParseException<string_type, string_adaptor> SAXParseExceptionT;
|
|
typedef XML::QualifiedName<string_type, string_adaptor> qualifiedNameT;
|
|
|
|
libxml2_wrapper();
|
|
~libxml2_wrapper();
|
|
|
|
////////////////////////////////////////////////
|
|
// configuration
|
|
virtual bool getFeature(const string_type& name) const;
|
|
virtual void setFeature(const string_type& name, bool value);
|
|
|
|
////////////////////////////////////////////////
|
|
// Event Handlers
|
|
virtual void setEntityResolver(entityResolverT& resolver) { entityResolver_ = &resolver; }
|
|
virtual entityResolverT* getEntityResolver() const { return entityResolver_; }
|
|
virtual void setDTDHandler(dtdHandlerT& handler) { dtdHandler_ = &handler; }
|
|
virtual dtdHandlerT* getDTDHandler() const { return dtdHandler_; }
|
|
virtual void setContentHandler(contentHandlerT& handler) { contentHandler_ = &handler; }
|
|
virtual contentHandlerT* getContentHandler() const { return contentHandler_; }
|
|
virtual void setErrorHandler(errorHandlerT& handler) { errorHandler_ = &handler; }
|
|
virtual errorHandlerT* getErrorHandler() const { return errorHandler_; }
|
|
virtual void setDeclHandler(declHandlerT& handler) { declHandler_ = &handler; }
|
|
virtual declHandlerT* getDeclHandler() const { return declHandler_; }
|
|
virtual void setLexicalHandler(lexicalHandlerT& handler) { lexicalHandler_ = &handler; }
|
|
virtual lexicalHandlerT* getLexicalHandler() const { return lexicalHandler_; }
|
|
|
|
////////////////////////////////////////////////
|
|
// parsing
|
|
virtual void parse(inputSourceT& source);
|
|
|
|
public:
|
|
virtual string_type getPublicId() const;
|
|
virtual string_type getSystemId() const;
|
|
virtual size_t getLineNumber() const;
|
|
virtual size_t getColumnNumber() const;
|
|
|
|
private:
|
|
virtual void SAXstartDocument();
|
|
virtual void SAXendDocument();
|
|
virtual void SAXlocator(xmlSAXLocatorPtr locator) { locator_ = locator; }
|
|
virtual void SAXcharacters(const xmlChar* ch, int len);
|
|
virtual void SAXcdata(const xmlChar* ch, int len);
|
|
virtual void SAXignorableWhitespace(const xmlChar* ch, int len);
|
|
virtual void SAXwarning(const std::string& warning);
|
|
virtual void SAXerror(const std::string& error);
|
|
virtual void SAXfatalError(const std::string& fatal);
|
|
virtual void SAXprocessingInstruction(const xmlChar* target, const xmlChar* data);
|
|
virtual void SAXcomment(const xmlChar* comment);
|
|
virtual void SAXstartCdataSection();
|
|
virtual void SAXendCdataSection();
|
|
virtual void SAXstartElement(const xmlChar* name, const xmlChar** attrs);
|
|
virtual void SAXstartElementNoNS(const xmlChar* name, const xmlChar** attrs);
|
|
virtual void SAXendElement(const xmlChar* name);
|
|
virtual void SAXendElementNoNS(const xmlChar* name);
|
|
virtual void SAXnotationDecl(const xmlChar *name, const xmlChar *publicId, const xmlChar *systemId);
|
|
virtual void SAXunparsedEntityDecl(const xmlChar *name, const xmlChar *publicId, const xmlChar *systemId, const xmlChar *notationName);
|
|
virtual void SAXelementDecl(const xmlChar* name, int type, xmlElementContentPtr content);
|
|
void convertXML_Content(std::ostream& os, int type, xmlElementContentPtr model, bool isChild) const;
|
|
virtual void SAXattributeDecl(const xmlChar *elem, const xmlChar *fullname, int type, int def, const xmlChar *defaultValue, xmlEnumerationPtr tree);
|
|
string_type stringAttrEnum(xmlEnumerationPtr tree, bool leadingSpace) const;
|
|
virtual void SAXentityDecl(const xmlChar *name, int type, const xmlChar *publicId, const xmlChar *systemId, xmlChar *content);
|
|
virtual xmlParserInputPtr SAXresolveEntity(const xmlChar* publicId, const xmlChar* systemId);
|
|
virtual xmlParserCtxtPtr parserContext() { return context_; }
|
|
|
|
|
|
qualifiedNameT processName(const string_type& qName, bool isAttribute);
|
|
void reportError(const std::string& message, bool fatal = false);
|
|
void checkNotParsing(const string_type& type, const string_type& name) const;
|
|
|
|
private:
|
|
// member variables
|
|
entityResolverT* entityResolver_;
|
|
dtdHandlerT* dtdHandler_;
|
|
contentHandlerT* contentHandler_;
|
|
errorHandlerT* errorHandler_;
|
|
namespaceSupportT nsSupport_;
|
|
declHandlerT* declHandler_;
|
|
lexicalHandlerT* lexicalHandler_;
|
|
|
|
xmlParserCtxtPtr context_;
|
|
xmlSAXLocatorPtr locator_;
|
|
|
|
bool parsing_;
|
|
|
|
bool namespaces_;
|
|
bool prefixes_;
|
|
bool isInCData_;
|
|
|
|
string_type emptyString_;
|
|
const FeatureNames<string_type, string_adaptor> features_;
|
|
const NamespaceConstants<string_type, string_adaptor> nsc_;
|
|
const AttributeDefaults<string_type, string_adaptor> attrDefaults_;
|
|
const AttributeTypes<string_type, string_adaptor> attrTypes_;
|
|
}; // class libxml2_wrapper
|
|
|
|
template<class string_type, class T0, class T1>
|
|
libxml2_wrapper<string_type, T0, T1>::libxml2_wrapper() :
|
|
entityResolver_(0),
|
|
dtdHandler_(0),
|
|
contentHandler_(0),
|
|
errorHandler_(0),
|
|
declHandler_(0),
|
|
lexicalHandler_(0),
|
|
locator_(0),
|
|
parsing_(false),
|
|
isInCData_(false),
|
|
namespaces_(true),
|
|
prefixes_(true)
|
|
{
|
|
context_ = xmlCreatePushParserCtxt(libxml2_wrapper_impl_tiddle::lwit_SaxHandler(),
|
|
reinterpret_cast<void*>(static_cast<libxml2_wrapper_impl_tiddle::libxml2_base*>(this)),
|
|
0,
|
|
0,
|
|
0);
|
|
xmlCtxtUseOptions(context_, XML_PARSE_DTDLOAD +
|
|
XML_PARSE_DTDVALID +
|
|
XML_PARSE_NOENT +
|
|
XML_PARSE_NOBLANKS);
|
|
} // libxml2_wrapper
|
|
|
|
template<class string_type, class T0, class T1>
|
|
libxml2_wrapper<string_type, T0, T1>::~libxml2_wrapper()
|
|
{
|
|
xmlFreeParserCtxt(context_);
|
|
} // ~libxml2_wrapper
|
|
|
|
template<class string_type, class T0, class T1>
|
|
bool libxml2_wrapper<string_type, T0, T1>::getFeature(const string_type& name) const
|
|
{
|
|
if(name == features_.namespaces)
|
|
return namespaces_;
|
|
|
|
if(name == features_.namespace_prefixes)
|
|
return prefixes_;
|
|
|
|
if(name == features_.validation)
|
|
return libxml2_wrapper_impl_tiddle::lwit_getFeature(context_, "validate");
|
|
|
|
if(name == features_.external_general)
|
|
return libxml2_wrapper_impl_tiddle::lwit_getFeature(context_, "fetch external entities");
|
|
|
|
if(name == features_.external_parameter)
|
|
{
|
|
throw SAX::SAXNotSupportedException(std::string("Feature not supported ") + string_adaptor::asStdString(name));
|
|
}
|
|
else
|
|
{
|
|
throw SAX::SAXNotRecognizedException(std::string("Feature not recognized ") + string_adaptor::asStdString(name));
|
|
}
|
|
} // getFeature
|
|
|
|
template<class string_type, class T0, class T1>
|
|
void libxml2_wrapper<string_type, T0, T1>::setFeature(const string_type& name, bool value)
|
|
{
|
|
if(name == features_.namespaces)
|
|
{
|
|
checkNotParsing(string_adaptor::construct_from_utf8("feature"), name);
|
|
namespaces_ = value;
|
|
if(!namespaces_ && !prefixes_)
|
|
prefixes_ = true;
|
|
return;
|
|
}
|
|
|
|
if(name == features_.namespace_prefixes)
|
|
{
|
|
checkNotParsing(string_adaptor::construct_from_utf8("feature"), name);
|
|
prefixes_ = value;
|
|
if(prefixes_ && !namespaces_)
|
|
namespaces_ = true;
|
|
return;
|
|
}
|
|
|
|
if(name == features_.validation)
|
|
{
|
|
libxml2_wrapper_impl_tiddle::lwit_setFeature(context_, "validate", value);
|
|
return;
|
|
} // if ...
|
|
|
|
if(name == features_.external_general)
|
|
{
|
|
libxml2_wrapper_impl_tiddle::lwit_setFeature(context_, "fetch external entities", value);
|
|
return;
|
|
} // if ...
|
|
|
|
if(name == features_.external_parameter)
|
|
{
|
|
std::ostringstream os;
|
|
os << "Feature not supported " << string_adaptor::asStdString(name);
|
|
throw SAX::SAXNotSupportedException(os.str());
|
|
}
|
|
else
|
|
{
|
|
std::ostringstream os;
|
|
os << "Feature not recognized " << string_adaptor::asStdString(name);
|
|
throw SAX::SAXNotRecognizedException(os.str());
|
|
}
|
|
} // setFeature
|
|
|
|
template<class string_type, class T0, class T1>
|
|
typename XML::QualifiedName<string_type, typename libxml2_wrapper<string_type, T0, T1>::string_adaptor> libxml2_wrapper<string_type, T0, T1>::processName(const string_type& qName, bool isAttribute)
|
|
{
|
|
qualifiedNameT p = nsSupport_.processName(qName, isAttribute);
|
|
if(string_adaptor::empty(p.namespaceUri()) && !string_adaptor::empty(p.prefix()))
|
|
reportError(std::string("Undeclared prefix ") + string_adaptor::asStdString(qName));
|
|
return p;
|
|
} // processName
|
|
|
|
template<class string_type, class T0, class T1>
|
|
void libxml2_wrapper<string_type, T0, T1>::reportError(const std::string& message, bool fatal)
|
|
{
|
|
if(!errorHandler_)
|
|
return;
|
|
|
|
SAXParseExceptionT e(message, *this);
|
|
if(fatal)
|
|
errorHandler_->fatalError(e);
|
|
else
|
|
errorHandler_->error(e);
|
|
} // reportError
|
|
|
|
template<class string_type, class T0, class T1>
|
|
void libxml2_wrapper<string_type, T0, T1>::checkNotParsing(const string_type& type, const string_type& name) const
|
|
{
|
|
if(parsing_)
|
|
{
|
|
std::ostringstream os;
|
|
os << "Can't change " << string_adaptor::asStdString(type) << " " << string_adaptor::asStdString(name) << " while parsing";
|
|
throw SAX::SAXNotSupportedException(os.str());
|
|
} // if(parsing_)
|
|
} // checkNotParsing
|
|
|
|
template<class string_type, class T0, class T1>
|
|
string_type libxml2_wrapper<string_type, T0, T1>::getPublicId() const
|
|
{
|
|
if(locator_)
|
|
return string_adaptor::construct_from_utf8(reinterpret_cast<const char*>(locator_->getPublicId(context_)));
|
|
return string_type();
|
|
} // getPublicId
|
|
|
|
template<class string_type, class T0, class T1>
|
|
string_type libxml2_wrapper<string_type, T0, T1>::getSystemId() const
|
|
{
|
|
if(locator_)
|
|
return string_adaptor::construct_from_utf8(reinterpret_cast<const char*>(locator_->getSystemId(context_)));
|
|
return string_type();
|
|
} // getSystemId
|
|
|
|
template<class string_type, class T0, class T1>
|
|
size_t libxml2_wrapper<string_type, T0, T1>::getLineNumber() const
|
|
{
|
|
if(locator_)
|
|
return locator_->getLineNumber(context_);
|
|
return -1;
|
|
} // getLineNumber
|
|
|
|
template<class string_type, class T0, class T1>
|
|
size_t libxml2_wrapper<string_type, T0, T1>::getColumnNumber() const
|
|
{
|
|
if(locator_)
|
|
return locator_->getColumnNumber(context_);
|
|
return -1;
|
|
} // getColumnNumber
|
|
|
|
template<class string_type, class T0, class T1>
|
|
void libxml2_wrapper<string_type, T0, T1>::parse(inputSourceT& source)
|
|
{
|
|
if(contentHandler_)
|
|
contentHandler_->setDocumentLocator(*this);
|
|
|
|
InputSourceResolver is(source, string_adaptor());
|
|
if(is.resolve() == 0)
|
|
return;
|
|
|
|
parsing_ = true;
|
|
|
|
while(!is.resolve()->eof())
|
|
{
|
|
char buffer[4096];
|
|
is.resolve()->read(buffer, sizeof(buffer));
|
|
xmlParseChunk(context_, buffer, (int)is.resolve()->gcount(), is.resolve()->eof());
|
|
} // while(!in.eof())
|
|
|
|
xmlCtxtResetPush(context_, 0, 0, 0, 0);
|
|
|
|
parsing_ = false;
|
|
} // parse
|
|
|
|
template<class string_type, class T0, class T1>
|
|
void libxml2_wrapper<string_type, T0, T1>::SAXstartDocument()
|
|
{
|
|
if(isInCData_)
|
|
SAXendCdataSection();
|
|
|
|
if(contentHandler_)
|
|
contentHandler_->startDocument();
|
|
} // SAXstartDocument
|
|
|
|
template<class string_type, class T0, class T1>
|
|
void libxml2_wrapper<string_type, T0, T1>::SAXendDocument()
|
|
{
|
|
if(isInCData_)
|
|
SAXendCdataSection();
|
|
|
|
if(contentHandler_)
|
|
contentHandler_->endDocument();
|
|
} // SAXendDocument
|
|
|
|
template<class string_type, class T0, class T1>
|
|
void libxml2_wrapper<string_type, T0, T1>::SAXcharacters(const xmlChar* ch, int len)
|
|
{
|
|
if(isInCData_)
|
|
SAXendCdataSection();
|
|
|
|
if(contentHandler_)
|
|
contentHandler_->characters(string_adaptor::construct_from_utf8(reinterpret_cast<const char*>(ch), len));
|
|
} // SAXcharacters
|
|
|
|
template<class string_type, class T0, class T1>
|
|
void libxml2_wrapper<string_type, T0, T1>::SAXcdata(const xmlChar* ch, int len)
|
|
{
|
|
if(contentHandler_)
|
|
contentHandler_->characters(string_adaptor::construct_from_utf8(reinterpret_cast<const char*>(ch), len));
|
|
} // SAXcdata
|
|
|
|
template<class string_type, class T0, class T1>
|
|
void libxml2_wrapper<string_type, T0, T1>::SAXignorableWhitespace(const xmlChar* ch, int len)
|
|
{
|
|
if(contentHandler_)
|
|
contentHandler_->ignorableWhitespace(string_adaptor::construct_from_utf8(reinterpret_cast<const char*>(ch), len));
|
|
} // SAXignorableWhitespace
|
|
|
|
template<class string_type, class T0, class T1>
|
|
void libxml2_wrapper<string_type, T0, T1>::SAXwarning(const std::string& warning)
|
|
{
|
|
if(errorHandler_)
|
|
errorHandler_->warning(SAXParseExceptionT(warning, *this));
|
|
} // warning
|
|
|
|
template<class string_type, class T0, class T1>
|
|
void libxml2_wrapper<string_type, T0, T1>::SAXerror(const std::string& error)
|
|
{
|
|
if(errorHandler_)
|
|
errorHandler_->error(SAXParseExceptionT(error, *this));
|
|
} // error
|
|
|
|
template<class string_type, class T0, class T1>
|
|
void libxml2_wrapper<string_type, T0, T1>::SAXfatalError(const std::string& fatal)
|
|
{
|
|
if(errorHandler_)
|
|
errorHandler_->fatalError(SAXParseExceptionT(fatal, *this));
|
|
} // fatal
|
|
|
|
template<class string_type, class T0, class T1>
|
|
void libxml2_wrapper<string_type, T0, T1>::SAXprocessingInstruction(const xmlChar* target, const xmlChar* data)
|
|
{
|
|
if(isInCData_)
|
|
SAXendCdataSection();
|
|
|
|
if(contentHandler_)
|
|
contentHandler_->processingInstruction(string_adaptor::construct_from_utf8(reinterpret_cast<const char*>(target)),
|
|
string_adaptor::construct_from_utf8(reinterpret_cast<const char*>(data)));
|
|
} // SAXprocessingInstruction
|
|
|
|
template<class string_type, class T0, class T1>
|
|
void libxml2_wrapper<string_type, T0, T1>::SAXcomment(const xmlChar* comment)
|
|
{
|
|
if(isInCData_)
|
|
SAXendCdataSection();
|
|
|
|
if(lexicalHandler_)
|
|
lexicalHandler_->comment(string_adaptor::construct_from_utf8(reinterpret_cast<const char*>(comment)));
|
|
} // SAXcomment
|
|
|
|
template<class string_type, class T0, class T1>
|
|
void libxml2_wrapper<string_type, T0, T1>::SAXstartCdataSection()
|
|
{
|
|
if (isInCData_)
|
|
return;
|
|
|
|
isInCData_ = true;
|
|
if(lexicalHandler_)
|
|
lexicalHandler_->startCDATA();
|
|
} // startCdataSection
|
|
|
|
template<class string_type, class T0, class T1>
|
|
void libxml2_wrapper<string_type, T0, T1>::SAXendCdataSection()
|
|
{
|
|
if (!isInCData_)
|
|
return;
|
|
|
|
if(lexicalHandler_)
|
|
lexicalHandler_->endCDATA();
|
|
isInCData_ = false;
|
|
} // endCdataSection
|
|
|
|
template<class string_type, class T0, class T1>
|
|
void libxml2_wrapper<string_type, T0, T1>::SAXstartElement(const xmlChar* qName, const xmlChar** atts)
|
|
{
|
|
|
|
if(isInCData_)
|
|
SAXendCdataSection();
|
|
|
|
if(!contentHandler_)
|
|
return;
|
|
|
|
if(!namespaces_)
|
|
{
|
|
SAXstartElementNoNS(qName, atts);
|
|
return;
|
|
} // if(!namespaces)
|
|
|
|
// OK we're doing Namespaces
|
|
nsSupport_.pushContext();
|
|
SAX::AttributesImpl<string_type, string_adaptor> attributes;
|
|
|
|
// take a first pass and copy all the attributes, noting any declarations
|
|
if(atts && *atts != 0)
|
|
{
|
|
const xmlChar** a1 = atts;
|
|
while(*a1 != 0)
|
|
{
|
|
string_type attQName = string_adaptor::construct_from_utf8(reinterpret_cast<const char*>(*a1++));
|
|
string_type value = string_adaptor::construct_from_utf8(reinterpret_cast<const char*>(*a1++));
|
|
|
|
// declaration?
|
|
if(string_adaptor::find(attQName, nsc_.xmlns) == 0)
|
|
{
|
|
string_type prefix;
|
|
typename string_adaptor::size_type n = string_adaptor::find(attQName, nsc_.colon);
|
|
if(n != string_adaptor::npos())
|
|
prefix = string_adaptor::construct(string_adaptor::begin(attQName) + n + 1, string_adaptor::end(attQName));
|
|
if(!nsSupport_.declarePrefix(prefix, value))
|
|
reportError(std::string("Illegal Namespace prefix ") + string_adaptor::asStdString(prefix));
|
|
contentHandler_->startPrefixMapping(prefix, value);
|
|
if(prefixes_)
|
|
attributes.addAttribute(emptyString_,
|
|
emptyString_,
|
|
attQName,
|
|
attributeTypeT::CDATA,
|
|
value);
|
|
}
|
|
} // while
|
|
|
|
while(*atts != 0)
|
|
{
|
|
string_type attQName = string_adaptor::construct_from_utf8(reinterpret_cast<const char*>(*atts++));
|
|
string_type value = string_adaptor::construct_from_utf8(reinterpret_cast<const char*>(*atts++));
|
|
|
|
// declaration?
|
|
if(string_adaptor::find(attQName, nsc_.xmlns) != 0)
|
|
{
|
|
qualifiedNameT attName = processName(attQName, true);
|
|
attributes.addAttribute(attName.namespaceUri(),
|
|
attName.localName(),
|
|
attName.rawName(),
|
|
attributeTypeT::CDATA,
|
|
value);
|
|
}
|
|
} // while ...
|
|
} // if ...
|
|
|
|
// at last! report the event
|
|
qualifiedNameT name = processName(string_adaptor::construct_from_utf8(reinterpret_cast<const char*>(qName)), false);
|
|
contentHandler_->startElement(name.namespaceUri(),
|
|
name.localName(),
|
|
name.rawName(),
|
|
attributes);
|
|
} // SAXstartElement
|
|
|
|
template<class string_type, class T0, class T1>
|
|
void libxml2_wrapper<string_type, T0, T1>::SAXstartElementNoNS(const xmlChar* qName, const xmlChar** atts)
|
|
{
|
|
SAX::AttributesImpl<string_type, string_adaptor> attributes;
|
|
|
|
if(isInCData_)
|
|
SAXendCdataSection();
|
|
|
|
if(atts && *atts != 0)
|
|
{
|
|
while(*atts != 0)
|
|
{
|
|
string_type attQName = string_adaptor::construct_from_utf8(reinterpret_cast<const char*>(*atts++));
|
|
string_type value = string_adaptor::construct_from_utf8(reinterpret_cast<const char*>(*atts++));
|
|
|
|
attributes.addAttribute(emptyString_,
|
|
emptyString_,
|
|
attQName,
|
|
attributeTypeT::CDATA,
|
|
value);
|
|
} // while ..
|
|
} // if ...
|
|
|
|
contentHandler_->startElement(emptyString_, emptyString_, string_adaptor::construct_from_utf8((reinterpret_cast<const char*>(qName))), attributes);
|
|
} // SAXstartElementNoNS
|
|
|
|
template<class string_type, class T0, class T1>
|
|
void libxml2_wrapper<string_type, T0, T1>::SAXendElement(const xmlChar* qName)
|
|
{
|
|
if(isInCData_)
|
|
SAXendCdataSection();
|
|
|
|
if(!contentHandler_)
|
|
return;
|
|
|
|
if(!namespaces_)
|
|
{
|
|
SAXendElementNoNS(qName);
|
|
return;
|
|
} // if(!namespaces_)
|
|
|
|
qualifiedNameT name = processName(string_adaptor::construct_from_utf8(reinterpret_cast<const char*>(qName)), false);
|
|
contentHandler_->endElement(name.namespaceUri(),
|
|
name.localName(),
|
|
name.rawName());
|
|
typename NamespaceSupport<string_type, string_adaptor>::stringListT prefixes = nsSupport_.getDeclaredPrefixes();
|
|
for(size_t i = 0, end = prefixes.size(); i < end; ++i)
|
|
contentHandler_->endPrefixMapping(prefixes[i]);
|
|
nsSupport_.popContext();
|
|
} // SAXendElement
|
|
|
|
template<class string_type, class T0, class T1>
|
|
void libxml2_wrapper<string_type, T0, T1>::SAXendElementNoNS(const xmlChar* qName)
|
|
{
|
|
if(isInCData_)
|
|
SAXendCdataSection();
|
|
|
|
if(contentHandler_)
|
|
contentHandler_->endElement(emptyString_, emptyString_, string_adaptor::construct_from_utf8(reinterpret_cast<const char*>(qName)));
|
|
} // SAXendElementNoNS
|
|
|
|
template<class string_type, class T0, class T1>
|
|
void libxml2_wrapper<string_type, T0, T1>::SAXnotationDecl(const xmlChar *name, const xmlChar *publicId, const xmlChar *systemId)
|
|
{
|
|
if(isInCData_)
|
|
SAXendCdataSection();
|
|
|
|
if(dtdHandler_)
|
|
dtdHandler_->notationDecl(string_adaptor::construct_from_utf8(reinterpret_cast<const char*>(name)),
|
|
string_adaptor::construct_from_utf8(reinterpret_cast<const char*>(publicId)),
|
|
string_adaptor::construct_from_utf8(reinterpret_cast<const char*>(systemId)));
|
|
} // SAXnotationDecl
|
|
|
|
template<class string_type, class T0, class T1>
|
|
void libxml2_wrapper<string_type, T0, T1>::SAXunparsedEntityDecl(const xmlChar *name, const xmlChar *publicId, const xmlChar *systemId, const xmlChar *notationName)
|
|
{
|
|
if(isInCData_)
|
|
SAXendCdataSection();
|
|
|
|
if(dtdHandler_)
|
|
dtdHandler_->unparsedEntityDecl(string_adaptor::construct_from_utf8(reinterpret_cast<const char*>(name)),
|
|
string_adaptor::construct_from_utf8(reinterpret_cast<const char*>(publicId)),
|
|
string_adaptor::construct_from_utf8(reinterpret_cast<const char*>(systemId)),
|
|
string_adaptor::construct_from_utf8(reinterpret_cast<const char*>(notationName)));
|
|
} // SAXunparsedEntityDecl
|
|
|
|
template<class string_type, class T0, class T1>
|
|
void libxml2_wrapper<string_type, T0, T1>::SAXelementDecl(const xmlChar* name, int type, xmlElementContentPtr content)
|
|
{
|
|
if(isInCData_)
|
|
SAXendCdataSection();
|
|
|
|
if(!declHandler_)
|
|
return;
|
|
|
|
std::ostringstream os;
|
|
convertXML_Content(os, type, content, false);
|
|
declHandler_->elementDecl(string_adaptor::construct_from_utf8(reinterpret_cast<const char*>(name)), string_adaptor::construct_from_utf8(os.str().c_str()));
|
|
} // elementDeclaration
|
|
|
|
template<class string_type, class T0, class T1>
|
|
void libxml2_wrapper<string_type, T0, T1>::convertXML_Content(std::ostream& os, int type, xmlElementContentPtr model, bool isChild) const
|
|
{
|
|
char concatenator = ' ';
|
|
|
|
switch(type)
|
|
{
|
|
case XML_ELEMENT_TYPE_EMPTY:
|
|
os << "EMPTY";
|
|
break;
|
|
case XML_ELEMENT_TYPE_ANY:
|
|
os << "ANY";
|
|
return;
|
|
case XML_ELEMENT_TYPE_MIXED:
|
|
if(model->c1 == 0)
|
|
os << "(#PCDATA)";
|
|
else
|
|
os << "(#PCDATA";
|
|
concatenator = '|';
|
|
break;
|
|
case XML_ELEMENT_TYPE_ELEMENT:
|
|
break;
|
|
} // switch
|
|
|
|
switch(model->type)
|
|
{
|
|
case XML_ELEMENT_CONTENT_ELEMENT:
|
|
if(!isChild)
|
|
os << '(' << model->name << ')';
|
|
else
|
|
os << model->name;
|
|
break;
|
|
case XML_ELEMENT_CONTENT_SEQ:
|
|
concatenator = ',';
|
|
break;
|
|
case XML_ELEMENT_CONTENT_OR:
|
|
concatenator = '|';
|
|
break;
|
|
case XML_ELEMENT_CONTENT_PCDATA:
|
|
break;
|
|
} // switch
|
|
|
|
// do children here
|
|
if(model->c1 != 0)
|
|
{
|
|
if(!isChild)
|
|
os << '(';
|
|
convertXML_Content(os, XML_ELEMENT_TYPE_ELEMENT, model->c1, true);
|
|
if(model->c2 != 0)
|
|
{
|
|
os << concatenator;
|
|
convertXML_Content(os, XML_ELEMENT_TYPE_ELEMENT, model->c2, true);
|
|
} // if ...
|
|
if(!isChild)
|
|
os << ')';
|
|
} // if ...
|
|
|
|
switch(model->ocur)
|
|
{
|
|
case XML_ELEMENT_CONTENT_ONCE:
|
|
break;
|
|
case XML_ELEMENT_CONTENT_OPT:
|
|
os << "?";
|
|
break;
|
|
case XML_ELEMENT_CONTENT_MULT:
|
|
os << "*";
|
|
break;
|
|
case XML_ELEMENT_CONTENT_PLUS:
|
|
os << "+";
|
|
break;
|
|
} // switch
|
|
} // convertXML_Content
|
|
|
|
template<class string_type, class T0, class T1>
|
|
void libxml2_wrapper<string_type, T0, T1>::SAXattributeDecl(const xmlChar *elem, const xmlChar *fullname, int type, int def, const xmlChar *defaultValue, xmlEnumerationPtr tree)
|
|
{
|
|
if(isInCData_)
|
|
SAXendCdataSection();
|
|
|
|
if(!declHandler_)
|
|
return;
|
|
|
|
const string_type* defType = &attrDefaults_.implied;
|
|
if(def)
|
|
defType = (defaultValue) ? &attrDefaults_.fixed : &attrDefaults_.required;
|
|
|
|
string_type typeStr;
|
|
switch(type)
|
|
{
|
|
case XML_ATTRIBUTE_CDATA:
|
|
typeStr = attrTypes_.cdata;
|
|
break;
|
|
case XML_ATTRIBUTE_ID:
|
|
typeStr = attrTypes_.id;
|
|
break;
|
|
case XML_ATTRIBUTE_IDREF :
|
|
typeStr = attrTypes_.idref;
|
|
break;
|
|
case XML_ATTRIBUTE_IDREFS:
|
|
typeStr = attrTypes_.idrefs;
|
|
break;
|
|
case XML_ATTRIBUTE_ENTITY:
|
|
typeStr = attrTypes_.entity;
|
|
break;
|
|
case XML_ATTRIBUTE_ENTITIES:
|
|
typeStr = attrTypes_.entities;
|
|
break;
|
|
case XML_ATTRIBUTE_NMTOKEN:
|
|
typeStr = attrTypes_.nmtoken;
|
|
break;
|
|
case XML_ATTRIBUTE_NMTOKENS:
|
|
typeStr = attrTypes_.nmtokens;
|
|
break;
|
|
case XML_ATTRIBUTE_ENUMERATION:
|
|
typeStr = stringAttrEnum(tree, false);
|
|
break;
|
|
case XML_ATTRIBUTE_NOTATION:
|
|
string_adaptor::append(typeStr, attrTypes_.notation);
|
|
string_adaptor::append(typeStr, stringAttrEnum(tree, true));
|
|
break;
|
|
} // switch(type)
|
|
|
|
declHandler_->attributeDecl(string_adaptor::construct_from_utf8(reinterpret_cast<const char*>(elem)),
|
|
string_adaptor::construct_from_utf8(reinterpret_cast<const char*>(fullname)),
|
|
typeStr,
|
|
*defType,
|
|
string_adaptor::construct_from_utf8(reinterpret_cast<const char*>(defaultValue)));
|
|
} // SAXattributeDecl
|
|
|
|
template<class string_type, class T0, class T1>
|
|
string_type libxml2_wrapper<string_type, T0, T1>::stringAttrEnum(xmlEnumerationPtr tree, bool leadingSpace) const
|
|
{
|
|
std::ostringstream os;
|
|
if(leadingSpace)
|
|
os << " ";
|
|
os << "(";
|
|
while(tree)
|
|
{
|
|
os << tree->name;
|
|
tree = tree->next;
|
|
if(tree)
|
|
os << " | ";
|
|
} // while
|
|
os << ")";
|
|
|
|
return string_adaptor::construct_from_utf8(os.str().c_str());
|
|
} // stringAttrEnum
|
|
|
|
template<class string_type, class T0, class T1>
|
|
void libxml2_wrapper<string_type, T0, T1>::SAXentityDecl(const xmlChar *name, int type, const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
|
|
{
|
|
if(isInCData_)
|
|
SAXendCdataSection();
|
|
|
|
if(!declHandler_)
|
|
return;
|
|
|
|
switch(type)
|
|
{
|
|
case 1: // internal
|
|
declHandler_->internalEntityDecl(string_adaptor::construct_from_utf8(reinterpret_cast<const char*>(name)),
|
|
string_adaptor::construct_from_utf8(reinterpret_cast<const char*>(content)));
|
|
break;
|
|
case 2: // external
|
|
declHandler_->externalEntityDecl(string_adaptor::construct_from_utf8(reinterpret_cast<const char*>(name)),
|
|
string_adaptor::construct_from_utf8(reinterpret_cast<const char*>(publicId)),
|
|
string_adaptor::construct_from_utf8(reinterpret_cast<const char*>(systemId)));
|
|
break;
|
|
} // switch
|
|
} // SAXentityDecl
|
|
|
|
template<class string_type, class T0, class T1>
|
|
xmlParserInputPtr libxml2_wrapper<string_type, T0, T1>::SAXresolveEntity(const xmlChar* publicId, const xmlChar* systemId)
|
|
{
|
|
if(!entityResolver_)
|
|
return xmlLoadExternalEntity(reinterpret_cast<const char*>(systemId),
|
|
reinterpret_cast<const char*>(publicId),
|
|
context_);
|
|
return 0;
|
|
} // SAXresolveEntity
|
|
|
|
|
|
} // namespace SAX
|
|
} // namespace Arabica
|
|
|
|
#endif
|