/* -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; tab-width:4; -*- */ /* * libopenraw - xmlhandler.cpp * * Copyright (C) 2008-2018 Hubert Figuiere * * This library is free software: you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see * . */ #include #include #include #include #include "xmlhandler.h" namespace xml { bool LtString::operator()(const xmlChar *s1, const xmlChar *s2) const { return strcmp((const char *)s1, (const char *)s2) < 0; } Context::Context(const HandlerPtr &handler) : m_handler(handler) { } Context::~Context() { } ContextPtr Context::startElement(const int32_t /*element*/) { return shared_from_this(); } void Context::endElement(const int32_t /*element*/) { } void Context::appendText(const xmlChar * /*content*/) { } Handler::Handler(const std::string &filename) : Context(HandlerPtr()) , m_reader(xmlNewTextReaderFilename(filename.c_str())) { } Handler::~Handler() { if (m_reader != NULL) { xmlFreeTextReader(m_reader); } } void Handler::mapTags(const tag_map_definition_t *map) { m_tag_map.clear(); const tag_map_definition_t *ptag = map; while (ptag->first != 0) { m_tag_map.insert( std::make_pair((const xmlChar *)ptag->first, ptag->second)); ptag++; } } int32_t Handler::getTagId(const xmlChar *tag) { if (tag == NULL) { return 0; } tag_map_t::const_iterator iter = m_tag_map.find(tag); if (iter == m_tag_map.end()) { fprintf(stderr, "Tag %s is unknown\n", tag); return 0; } return iter->second; } Option Handler::getAttribute(const char* name) { if (!m_reader) { fprintf(stderr, "m_reader is NULL\n"); return OptionNone(); } xmlChar* attr = xmlTextReaderGetAttribute(m_reader, (const xmlChar*)name); if (attr == NULL) { return OptionNone(); } std::string sattr(reinterpret_cast(attr)); xmlFree(attr); return option_some(std::move(sattr)); } bool Handler::process() { if (m_reader == NULL) { return false; } m_contexts.push(shared_from_this()); int ret = xmlTextReaderRead(m_reader); while (ret == 1) { int node_type = xmlTextReaderNodeType(m_reader); switch (node_type) { case XML_READER_TYPE_ELEMENT: { int32_t element = getTagId(xmlTextReaderConstName(m_reader)); ContextPtr context = m_contexts.top()->startElement(element); m_contexts.push(context); break; } case XML_READER_TYPE_TEXT: { const xmlChar *content = xmlTextReaderConstValue(m_reader); m_contexts.top()->appendText(content); break; } case XML_READER_TYPE_END_ELEMENT: { int32_t element = getTagId(xmlTextReaderConstName(m_reader)); m_contexts.top()->endElement(element); m_contexts.pop(); break; } default: break; } ret = xmlTextReaderRead(m_reader); } // make sure we clear the contexts. while (!m_contexts.empty()) { m_contexts.pop(); } return true; } SimpleElementContext::SimpleElementContext(const HandlerPtr &handler, std::string &content) : Context(handler) , m_content(content) { } void SimpleElementContext::appendText(const xmlChar *content) { m_content += (const char *)content; } }