#ifndef ARABICA_SAX_LIBXML2_H #define ARABICA_SAX_LIBXML2_H //////////////////////////////////////////////////////////////// // A SAX2 Wrapper for libxml2 // // $Id$ //////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Arabica { namespace SAX { //////////////////////////////////////////////////////////////////////////// // the callback functions for libxml namespace libxml2_wrapper_impl_tiddle { extern "C" { 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 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; 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_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 xmlParserInputPtr lwit_resolveEntity(void* user_data, const xmlChar* publicId, const xmlChar* systemId); }; // class libxml2_base 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_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); xmlParserInputPtr lwit_resolveEntity(void* user_data, const xmlChar* publicId, const xmlChar* systemId); xmlSAXHandler* lwit_SaxHandler(); } // extern "C" } // namespace libxml2_wrapper_impl_tiddle template class libxml2_wrapper : public XMLReaderInterface, public Locator::string_adaptor>, protected libxml2_wrapper_impl_tiddle::libxml2_base { public: typedef XMLReaderInterface XMLReaderT; typedef typename XMLReaderT::string_adaptor string_adaptor; typedef SAX::EntityResolver entityResolverT; typedef SAX::DTDHandler dtdHandlerT; typedef SAX::ContentHandler contentHandlerT; typedef SAX::Attributes attributesT; typedef SAX::AttributeType attributeTypeT; typedef SAX::DeclHandler declHandlerT; typedef SAX::LexicalHandler lexicalHandlerT; typedef SAX::InputSource inputSourceT; typedef SAX::Locator locatorT; typedef SAX::NamespaceSupport namespaceSupportT; typedef SAX::ErrorHandler errorHandlerT; typedef SAX::SAXParseException SAXParseExceptionT; typedef typename XMLReaderT::PropertyBase PropertyBaseT; typedef typename XMLReaderT::template Property getLexicalHandlerT; typedef typename XMLReaderT::template Property setLexicalHandlerT; typedef typename XMLReaderT::template Property getDeclHandlerT; typedef typename XMLReaderT::template Property setDeclHandlerT; 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); protected: //////////////////////////////////////////////// // properties virtual std::auto_ptr doGetProperty(const string_type& name); virtual void doSetProperty(const string_type& name, std::auto_ptr value); public: virtual string_type getPublicId() const; virtual string_type getSystemId() const; virtual int getLineNumber() const; virtual int 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 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 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); typename NamespaceSupport::Parts 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_; string_type emptyString_; const FeatureNames features_; const PropertyNames properties_; const NamespaceConstants nsc_; const AttributeDefaults attrDefaults_; const AttributeTypes attrTypes_; }; // class libxml2_wrapper template libxml2_wrapper::libxml2_wrapper() : entityResolver_(0), dtdHandler_(0), contentHandler_(0), errorHandler_(0), declHandler_(0), lexicalHandler_(0), locator_(0), parsing_(false), namespaces_(true), prefixes_(true) { context_ = xmlCreatePushParserCtxt(libxml2_wrapper_impl_tiddle::lwit_SaxHandler(), reinterpret_cast(static_cast(this)), 0, 0, 0); xmlCtxtUseOptions(context_, XML_PARSE_DTDLOAD + XML_PARSE_DTDVALID + XML_PARSE_NOBLANKS); } // libxml2_wrapper template libxml2_wrapper::~libxml2_wrapper() { xmlFreeParserCtxt(context_); } // ~libxml2_wrapper template bool libxml2_wrapper::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 void libxml2_wrapper::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 #ifndef ARABICA_VS6_WORKAROUND std::auto_ptr::PropertyBaseT> libxml2_wrapper::doGetProperty(const string_type& name) #else std::auto_ptr::PropertyBaseT> libxml2_wrapper::doGetProperty(const string_type& name) #endif { if(name == properties_.declHandler) { getDeclHandlerT* prop = new getDeclHandlerT(declHandler_); return std::auto_ptr(prop); } if(name == properties_.lexicalHandler) { getLexicalHandlerT* prop = new getLexicalHandlerT(lexicalHandler_); return std::auto_ptr(prop); } throw SAX::SAXNotRecognizedException(std::string("Property not recognized ") + string_adaptor::asStdString(name)); } // doGetProperty template void libxml2_wrapper::doSetProperty(const string_type& name, std::auto_ptr value) { if(name == properties_.declHandler) { setDeclHandlerT* prop = dynamic_cast(value.get()); if(!prop) throw std::bad_cast(); declHandler_ = &(prop->get()); } if(name == properties_.lexicalHandler) { setLexicalHandlerT* prop = dynamic_cast(value.get()); if(!prop) throw std::bad_cast(); lexicalHandler_ = &(prop->get()); } throw SAX::SAXNotRecognizedException(std::string("Property not recognized ") + string_adaptor::asStdString(name)); } // doSetProperty template typename SAX::NamespaceSupport::string_adaptor>::Parts libxml2_wrapper::processName(const string_type& qName, bool isAttribute) { typename NamespaceSupport::Parts p = nsSupport_.processName(qName, isAttribute); if(string_adaptor::empty(p.URI) && !string_adaptor::empty(p.prefix)) reportError(std::string("Undeclared prefix ") + string_adaptor::asStdString(qName)); return p; } // processName template void libxml2_wrapper::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 void libxml2_wrapper::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 string_type libxml2_wrapper::getPublicId() const { if(locator_) return string_adaptor::construct_from_utf8(reinterpret_cast(locator_->getPublicId(context_))); return string_type(); } // getPublicId template string_type libxml2_wrapper::getSystemId() const { if(locator_) return string_adaptor::construct_from_utf8(reinterpret_cast(locator_->getSystemId(context_))); return string_type(); } // getSystemId template int libxml2_wrapper::getLineNumber() const { if(locator_) return locator_->getLineNumber(context_); return -1; } // getLineNumber template int libxml2_wrapper::getColumnNumber() const { if(locator_) return locator_->getColumnNumber(context_); return -1; } // getColumnNumber template void libxml2_wrapper::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, is.resolve()->gcount(), is.resolve()->eof()); } // while(!in.eof()) xmlCtxtResetPush(context_, 0, 0, 0, 0); parsing_ = false; } // parse template void libxml2_wrapper::SAXstartDocument() { if(contentHandler_) contentHandler_->startDocument(); } // SAXstartDocument template void libxml2_wrapper::SAXendDocument() { if(contentHandler_) contentHandler_->endDocument(); } // SAXendDocument template void libxml2_wrapper::SAXcharacters(const xmlChar* ch, int len) { if(contentHandler_) contentHandler_->characters(string_adaptor::construct_from_utf8(reinterpret_cast(ch), len)); } // SAXcharacters template void libxml2_wrapper::SAXignorableWhitespace(const xmlChar* ch, int len) { if(contentHandler_) contentHandler_->ignorableWhitespace(string_adaptor::construct_from_utf8(reinterpret_cast(ch), len)); } // SAXignorableWhitespace template void libxml2_wrapper::SAXwarning(const std::string& warning) { if(errorHandler_) errorHandler_->warning(SAXParseExceptionT(warning, *this)); } // warning template void libxml2_wrapper::SAXerror(const std::string& error) { if(errorHandler_) errorHandler_->error(SAXParseExceptionT(error, *this)); } // error template void libxml2_wrapper::SAXfatalError(const std::string& fatal) { if(errorHandler_) errorHandler_->fatalError(SAXParseExceptionT(fatal, *this)); } // fatal template void libxml2_wrapper::SAXprocessingInstruction(const xmlChar* target, const xmlChar* data) { if(contentHandler_) contentHandler_->processingInstruction(string_adaptor::construct_from_utf8(reinterpret_cast(target)), string_adaptor::construct_from_utf8(reinterpret_cast(data))); } // SAXprocessingInstruction template void libxml2_wrapper::SAXcomment(const xmlChar* comment) { if(lexicalHandler_) lexicalHandler_->comment(string_adaptor::construct_from_utf8(reinterpret_cast(comment))); } // SAXcomment template void libxml2_wrapper::SAXstartElement(const xmlChar* qName, const xmlChar** atts) { if(!contentHandler_) return; if(!namespaces_) { SAXstartElementNoNS(qName, atts); return; } // if(!namespaces) // OK we're doing Namespaces nsSupport_.pushContext(); SAX::AttributesImpl 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(*a1++)); string_type value = string_adaptor::construct_from_utf8(reinterpret_cast(*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(*atts++)); string_type value = string_adaptor::construct_from_utf8(reinterpret_cast(*atts++)); // declaration? if(string_adaptor::find(attQName, nsc_.xmlns) != 0) { typename NamespaceSupport::Parts attName = processName(attQName, true); attributes.addAttribute(attName.URI, attName.localName, attName.rawName, attributeTypeT::CDATA, value); } } // while ... } // if ... // at last! report the event typename NamespaceSupport::Parts name = processName(string_adaptor::construct_from_utf8(reinterpret_cast(qName)), false); contentHandler_->startElement(name.URI, name.localName, name.rawName, attributes); } // SAXstartElement template void libxml2_wrapper::SAXstartElementNoNS(const xmlChar* qName, const xmlChar** atts) { SAX::AttributesImpl attributes; if(atts && *atts != 0) { while(*atts != 0) { string_type attQName = string_adaptor::construct_from_utf8(reinterpret_cast(*atts++)); string_type value = string_adaptor::construct_from_utf8(reinterpret_cast(*atts++)); attributes.addAttribute(emptyString_, emptyString_, attQName, attributeTypeT::CDATA, value); } // while .. } // if ... contentHandler_->startElement(emptyString_, emptyString_, string_adaptor::construct_from_utf8((reinterpret_cast(qName))), attributes); } // SAXstartElementNoNS template void libxml2_wrapper::SAXendElement(const xmlChar* qName) { if(!contentHandler_) return; if(!namespaces_) { SAXendElementNoNS(qName); return; } // if(!namespaces_) typename NamespaceSupport::Parts name = processName(string_adaptor::construct_from_utf8(reinterpret_cast(qName)), false); contentHandler_->endElement(name.URI, name.localName, name.rawName); typename NamespaceSupport::stringListT prefixes = nsSupport_.getDeclaredPrefixes(); for(size_t i = 0, end = prefixes.size(); i < end; ++i) contentHandler_->endPrefixMapping(prefixes[i]); nsSupport_.popContext(); } // SAXendElement template void libxml2_wrapper::SAXendElementNoNS(const xmlChar* qName) { if(contentHandler_) contentHandler_->endElement(emptyString_, emptyString_, string_adaptor::construct_from_utf8(reinterpret_cast(qName))); } // SAXendElementNoNS template void libxml2_wrapper::SAXnotationDecl(const xmlChar *name, const xmlChar *publicId, const xmlChar *systemId) { if(dtdHandler_) dtdHandler_->notationDecl(string_adaptor::construct_from_utf8(reinterpret_cast(name)), string_adaptor::construct_from_utf8(reinterpret_cast(publicId)), string_adaptor::construct_from_utf8(reinterpret_cast(systemId))); } // SAXnotationDecl template void libxml2_wrapper::SAXunparsedEntityDecl(const xmlChar *name, const xmlChar *publicId, const xmlChar *systemId, const xmlChar *notationName) { if(dtdHandler_) dtdHandler_->unparsedEntityDecl(string_adaptor::construct_from_utf8(reinterpret_cast(name)), string_adaptor::construct_from_utf8(reinterpret_cast(publicId)), string_adaptor::construct_from_utf8(reinterpret_cast(systemId)), string_adaptor::construct_from_utf8(reinterpret_cast(notationName))); } // SAXunparsedEntityDecl template void libxml2_wrapper::SAXelementDecl(const xmlChar* name, int type, xmlElementContentPtr content) { if(!declHandler_) return; std::ostringstream os; convertXML_Content(os, type, content, false); declHandler_->elementDecl(string_adaptor::construct_from_utf8(reinterpret_cast(name)), string_adaptor::construct_from_utf8(os.str().c_str())); } // elementDeclaration template void libxml2_wrapper::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 void libxml2_wrapper::SAXattributeDecl(const xmlChar *elem, const xmlChar *fullname, int type, int def, const xmlChar *defaultValue, xmlEnumerationPtr tree) { 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(elem)), string_adaptor::construct_from_utf8(reinterpret_cast(fullname)), typeStr, *defType, string_adaptor::construct_from_utf8(reinterpret_cast(defaultValue))); } // SAXattributeDecl template string_type libxml2_wrapper::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 void libxml2_wrapper::SAXentityDecl(const xmlChar *name, int type, const xmlChar *publicId, const xmlChar *systemId, xmlChar *content) { if(!declHandler_) return; switch(type) { case 1: // internal declHandler_->internalEntityDecl(string_adaptor::construct_from_utf8(reinterpret_cast(name)), string_adaptor::construct_from_utf8(reinterpret_cast(content))); break; case 2: // external declHandler_->externalEntityDecl(string_adaptor::construct_from_utf8(reinterpret_cast(name)), string_adaptor::construct_from_utf8(reinterpret_cast(publicId)), string_adaptor::construct_from_utf8(reinterpret_cast(systemId))); break; } // switch } // SAXentityDecl template xmlParserInputPtr libxml2_wrapper::SAXresolveEntity(const xmlChar* publicId, const xmlChar* systemId) { if(!entityResolver_) return xmlLoadExternalEntity(reinterpret_cast(systemId), reinterpret_cast(publicId), context_); return 0; } // SAXresolveEntity } // namespace SAX } // namespace Arabica #endif