arabica/include/SAX/wrappers/saxlibxml2.hpp
Jez Higgins 6bf75264de Completely removed XMLReader setProperty and getProperty member functions.
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.
2020-04-16 20:23:59 +01:00

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