Commit 1c5287339bb40cbe796b7b40646e736d983b66e7

Authored by Peter M. Groen
0 parents

Setting up a first attempt

.gitignore 0 โ†’ 100644
  1 +++ a/.gitignore
  1 +/CMakeLists.txt.user
  2 +build/
  3 +submodules/
  4 +.gitmodules
CMakeLists.txt 0 โ†’ 100644
  1 +++ a/CMakeLists.txt
  1 +cmake_minimum_required(VERSION 3.10)
  2 +project(osdev_xml)
  3 +LIST(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/submodules/cmake)
  4 +
  5 +# =================================================================
  6 +# = Include build information
  7 +include(projectheader)
  8 +project_header(osdev_xml)
  9 +
  10 +add_subdirectory(src)
  11 +#add_subdirectory(test)
  12 +#add_subdirectory(examples)
  13 +
  14 +include(packaging)
  15 +package_component()
  16 +
scripts/setup_submodules 0 โ†’ 100755
  1 +++ a/scripts/setup_submodules
  1 +#!/bin/bash
  2 +
  3 +# ===============================================
  4 +# == Setting some environment variables
  5 +# ===============================================
  6 +GIT_URL_OPEN="http://gitlab.osdev.nl/open_source"
  7 +GIT_URL_CLOSED="git@gitlab.osdev.nl:closed_source"
  8 +
  9 +FUNC_RESULT="-1"
  10 +
  11 +# Name : print_usage_exit()
  12 +# Description : Print the way this script is intended to be used and exit.
  13 +# Parameters : None.
  14 +# Returns : err_code 1 to the Operating System
  15 +# --------------------------------------------------------------------------------------
  16 +function print_usage_exit()
  17 +{
  18 + echo "Usage $0 -i|--install|-u|--update"
  19 + echo " -i or --install Install the submodules mentioned in the submodules.list"
  20 + echo " -u or --update Update the submodules mentioned in the submodules.list"
  21 + echo " "
  22 + exit 1
  23 +}
  24 +
  25 +# Name : check_top_or_sub
  26 +# Description : Determine if we're running in a "single" lib-build or part of a
  27 +# "meta"-repository ( submodule ).
  28 +# Parameters : None
  29 +# Returns : Updates the value FUNC_RESULT.
  30 +# -1 - We're neither a git-repo or submodule.
  31 +# 0 - We're a submodule
  32 +# 1 - We're a top-repo ( Single library )
  33 +# --------------------------------------------------------------------------------------
  34 +function check_top_or_sub()
  35 +{
  36 + # This function checks if we're the top-repository.
  37 + # In that case we need the submodules.. If we're already a submodule,
  38 + # we simply exit this script with a message
  39 + if [ -e ./.git ]; then
  40 + FUNC_RESULT="1"
  41 + return
  42 + elif [ -e ../.git ]; then
  43 + if [ -e ../.submodules ]; then
  44 + echo "Seems like we're already a submodule. Nothing to do here."
  45 + FUNC_RESULT="0"
  46 + return
  47 + fi
  48 + fi
  49 + FUNC_RESULT="-1"
  50 + return
  51 +}
  52 +
  53 +# Name : check_working_dir
  54 +# Description : If we're in the top of our repo, we can run this script further.
  55 +# Parameters : None.
  56 +# Returns : Updates the value FUNC_RESULT.
  57 +# -1 - Not used.
  58 +# 0 - We're not on the top-level
  59 +# 1 - We're at the top-level. Good to go.
  60 +# --------------------------------------------------------------------------------------
  61 +function check_working_dir()
  62 +{
  63 + FUNC_RESULT="-1"
  64 + # Check if we're in the top-level directory of our repository.
  65 + if [ -f ./scripts/submodules.list ]; then
  66 + # We're good to go
  67 + FUNC_RESULT="1"
  68 + return
  69 + fi
  70 + FUNC_RESULT="0"
  71 + return
  72 +}
  73 +
  74 +# Name : read_submodules
  75 +# Description : Read the list of submodules needed for this project
  76 +# Parameters : None
  77 +# Returns : Updates the value FUNC_RESULT
  78 +# 0 - Module list was not found
  79 +# 1 - Module list was found and read.
  80 +# --------------------------------------------------------------------------------------
  81 +function read_submodules()
  82 +{
  83 + FUNC_RESULT="-1"
  84 + if [ -e ./scripts/submodules.list ]; then
  85 + source ./scripts/submodules.list
  86 + FUNC_RESULT="1"
  87 + return
  88 + fi
  89 +
  90 + echo "Submodules list not found...."
  91 + FUNC_RESULT="0"
  92 + return
  93 +}
  94 +
  95 +# Name : add_submodules
  96 +# Description : Configure the repo to add the submodules.
  97 +# Parameters : None.
  98 +# Returns : None.
  99 +# --------------------------------------------------------------------------------------
  100 +function add_submodules()
  101 +{
  102 + echo -e "Adding SubModule(s)."
  103 + for SUB_MODULE in ${SUB_MODULES_OPEN}
  104 + do
  105 + git submodule add -f ${GIT_URL_OPEN}/${SUB_MODULE}.git submodules/${SUB_MODULE}
  106 + git config submodule.${SUB_MODULE}.url ${GIT_URL_OPEN}/${SUB_MODULE}.git
  107 + done
  108 +
  109 + for SUB_MODULE in ${SUB_MODULES_CLOSED}
  110 + do
  111 + echo {GIT_URL_CLOSED}/${SUB_MODULE}.git
  112 + git submodule add -f ${GIT_URL_CLOSED}/${SUB_MODULE}.git submodules/${SUB_MODULE}
  113 + git config submodule.${SUB_MODULE}.url ${GIT_URL_CLOSED}/${SUB_MODULE}.git
  114 + done
  115 +
  116 +}
  117 +
  118 +# Name : get_submodules
  119 +# Description : Actually get the submodules from gitlab and add them.
  120 +# Parameters : None
  121 +# Returns : None
  122 +# --------------------------------------------------------------------------------------
  123 +function get_submodules()
  124 +{
  125 + git submodule update --init --recursive
  126 +}
  127 +
  128 +# Name : update_submodules
  129 +# Description : Update the submodules already added.
  130 +# Parameters : None
  131 +# Returns : None
  132 +# --------------------------------------------------------------------------------------
  133 +function update_submodules()
  134 +{
  135 + git submodule update --recursive
  136 +}
  137 +
  138 +# =============================================================================
  139 +# == T H E M A I N E N T R Y O F T H I S S C R I P T ==
  140 +# =============================================================================
  141 +check_top_or_sub
  142 +if [ "${FUNC_RESULT}" == "0" ]; then
  143 + echo "Seems like we're a submodule already or not part of a repository."
  144 + exit 0
  145 +fi
  146 +
  147 +check_working_dir
  148 +if [ "${FUNC_RESULT}" == "0" ]; then
  149 + echo "Go to the top of this repository and type : scripts/setup_submodules [-i|--install]"
  150 + exit 0
  151 +fi
  152 +
  153 +read_submodules
  154 +
  155 +case "$1" in
  156 + -i*|--install*)
  157 + echo "Installing submodules for this repository ( ${PWD} )"
  158 + add_submodules
  159 + get_submodules
  160 + ;;
  161 + -u*|--update*)
  162 + echo "Update submodules : ${SUB_MODULES}"
  163 + update_submodules
  164 + ;;
  165 + *)
  166 + echo "No parameters found..."
  167 + print_usage_exit
  168 + ;;
  169 +esac
  170 +
scripts/submodules.list 0 โ†’ 100644
  1 +++ a/scripts/submodules.list
  1 +SUB_MODULES_OPEN="cmake
  2 +logger"
  3 +
  4 +SUB_MODULES_CLOSED=""
src/CMakeLists.txt 0 โ†’ 100644
  1 +++ a/src/CMakeLists.txt
  1 +cmake_minimum_required(VERSION 3.0)
  2 +LIST(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../cmake)
  3 +include(projectheader)
  4 +project_header(config)
  5 +
  6 +find_package( Qt5Core REQUIRED )
  7 +
  8 +include_directories( SYSTEM
  9 + ${Qt5Core_INCLUDE_DIRS}
  10 +)
  11 +
  12 +include(compiler)
  13 +
  14 +include_directories(
  15 + ${CMAKE_SOURCE_DIR}/submodules/logger/src
  16 +)
  17 +
  18 +set(SRC_LIST
  19 + ${CMAKE_CURRENT_SOURCE_DIR}/dcxmlbase.h
  20 + ${CMAKE_CURRENT_SOURCE_DIR}/dcxmlbase.cpp
  21 +)
  22 +
  23 +link_directories(
  24 + ${CMAKE_BINARY_DIR}/lib
  25 +)
  26 +
  27 +include(library)
  28 +add_libraries(
  29 + ${Qt5Core_LIBRARIES}
  30 + pugixml
  31 + logger
  32 +)
  33 +
  34 +include(installation)
  35 +install_component()
src/dcxmlbase.cpp 0 โ†’ 100644
  1 +++ a/src/dcxmlbase.cpp
  1 +#include "dcxmlbase.h"
  2 +#include "log.h"
  3 +
  4 +/*
  5 + * ________________________________________
  6 + * / Distance doesn't make you any smaller, \
  7 + * | but it does make you part of a larger |
  8 + * \ picture. /
  9 + * ----------------------------------------
  10 + * \
  11 + * \
  12 + * .--.
  13 + * |o_o |
  14 + * |:_/ |
  15 + * // \ \
  16 + * (| | )
  17 + * /'\_ _/`\
  18 + * \___)=(___/
  19 + *
  20 + **********************************************************/
  21 +
  22 +using namespace osdev::components::xml;
  23 +using namespace osdev::components::log;
  24 +
  25 +void xml_string_writer::write(const void* data, size_t size)
  26 +{
  27 + result += std::string(static_cast<const char*>(data), size);
  28 +}
  29 +
  30 +DcXmlBase::DcXmlBase(const QString& xmlFile)
  31 + : m_xmldoc()
  32 + , m_xPathHash()
  33 +{
  34 + if (!xmlFile.isNull() || !xmlFile.isEmpty()) {
  35 + if (parseFile(xmlFile)) {
  36 + LogDebug("[DcXmlBase::DcXmlBase]", QString("File : %1 ..............[OK].").arg(xmlFile).toStdString());
  37 + }
  38 + else {
  39 + LogError("[DcXmlBase::DcXmlBase]", QString("File : %1 ..............[Failed].").arg(xmlFile).toStdString());
  40 + throw std::runtime_error("[DcXmlBase::DcXmlBase] parseFile failed");
  41 + }
  42 + }
  43 +}
  44 +
  45 +DcXmlBase::~DcXmlBase() = default;
  46 +
  47 +bool DcXmlBase::parseString(const QString& qsXml)
  48 +{
  49 + bool bResult = false;
  50 +
  51 + if (!qsXml.isEmpty()) {
  52 + pugi::xml_parse_status parseStatus = m_xmldoc.load_buffer(qsXml.toStdString().c_str(),
  53 + qsXml.toStdString().size())
  54 + .status;
  55 + bResult = checkError(parseStatus);
  56 + }
  57 +
  58 + return bResult;
  59 +}
  60 +
  61 +bool DcXmlBase::parseFile(const QString& qsXml)
  62 +{
  63 + bool bResult = false;
  64 +
  65 + if (!qsXml.isEmpty()) {
  66 + pugi::xml_parse_status parseStatus = m_xmldoc.load_file(qsXml.toStdString().c_str()).status;
  67 + bResult = checkError(parseStatus);
  68 + }
  69 +
  70 + return bResult;
  71 +}
  72 +
  73 +bool DcXmlBase::checkError(pugi::xml_parse_status _parseStatus)
  74 +{
  75 + bool bResult = false;
  76 + QString sLogMessage = "An unknown error occured.";
  77 +
  78 +/*
  79 +* GCC 5.3.1 insits on all enumeration cases for this switch to be specified.
  80 +* The enumeration cases that throws -Wswitch warning are not available in pugixml for FC21.
  81 +* For backward compatibility with older pugixml version "-Wswitch" warnings are temporarily supressed.
  82 +*/
  83 +#pragma GCC diagnostic push
  84 +#pragma GCC diagnostic ignored "-Wswitch"
  85 + switch (_parseStatus) {
  86 + case pugi::status_ok:
  87 + sLogMessage = "File parsed successfully.";
  88 + bResult = true;
  89 + break;
  90 + case pugi::status_file_not_found:
  91 + sLogMessage = "File not found.";
  92 + break;
  93 + case pugi::status_io_error:
  94 + sLogMessage = "Some I/O Error occured during reading the file / stream. Check the hardware for errors.";
  95 + break;
  96 + case pugi::status_out_of_memory:
  97 + sLogMessage = "Out of Memory while parsing the file.";
  98 + break;
  99 + case pugi::status_internal_error:
  100 + sLogMessage = "Oh dear... That's different. Something went horribly wrong. It is unrecoverable. We're exiting the whole shabang..";
  101 + break;
  102 + case pugi::status_unrecognized_tag:
  103 + sLogMessage = "Parsing stopping due to a tag with either an empty name or a name which starts with an incorrect character (Left a '#' somewhere?)";
  104 + break;
  105 + case pugi::status_bad_pi:
  106 + sLogMessage = "Parsing stopped due to incorrect document declaration/processing instruction. ";
  107 + break;
  108 + case pugi::status_bad_comment:
  109 + sLogMessage = "Parsing stopped due to the invalid construct of a Comment.";
  110 + break;
  111 + case pugi::status_bad_cdata:
  112 + sLogMessage = "Parsing stopped due to the invalid construct of a CDATA section.";
  113 + break;
  114 + case pugi::status_bad_doctype:
  115 + sLogMessage = "Parsing stopped due to the invalid construct of a DocType.";
  116 + break;
  117 + case pugi::status_bad_pcdata:
  118 + sLogMessage = "Parsing stopped due to the invalid construct of a PCDATA section.";
  119 + break;
  120 + case pugi::status_bad_attribute:
  121 + sLogMessage = "Parsing stopped because there was an incorrect attribute, such as an attribute without value or with value that is not quoted (note that <node attr=1> is incorrect in XML).";
  122 + break;
  123 + case pugi::status_bad_start_element:
  124 + sLogMessage = "Parsing stopped because a starting tag either had no closing > symbol or contained some incorrect symbol.";
  125 + break;
  126 + case pugi::status_bad_end_element:
  127 + sLogMessage = "Parsing stopped because ending tag had incorrect syntax (i.e. extra non-whitespace symbols between tag name and >).";
  128 + break;
  129 + case pugi::status_end_element_mismatch:
  130 + sLogMessage = "parsing stopped because the closing tag did not match the opening one (i.e. <node></nedo>) or because some tag was not closed at all.";
  131 + break;
  132 + // DISABLED ON FEDORA 21 and CentOS 7. Not present in pugixml 1.0-8.fc21
  133 + // case pugi::status_append_invalid_root:
  134 + // case pugi::status_no_document_element:
  135 + }
  136 +#pragma GCC diagnostic pop
  137 + LogDebug("[DcXmlBase::checkError]", sLogMessage.toStdString());
  138 + return bResult;
  139 +}
  140 +
  141 +void DcXmlBase::addXPath(const QString& qsName, const QString& qsXPath)
  142 +{
  143 + if (m_xPathHash.contains(qsName)) {
  144 + LogWarning("[DcXmlBase::addXPath]", std::string( "XPath already registered : " + qsName.toStdString()));
  145 + }
  146 + m_xPathHash.insert(qsName, qsXPath);
  147 +
  148 + LogDebug("[DcXmlBase::addXPath]", std::string("XPath" + qsXPath.toStdString() + " registered with key : " + qsName.toStdString()));
  149 +}
  150 +
  151 +QString DcXmlBase::getXPath(const QString& qsXPathSelect) const
  152 +{
  153 + QString qsXPath = m_xPathHash.value(qsXPathSelect);
  154 +
  155 + if (qsXPath.isEmpty()) {
  156 + LogWarning("dcxml", "XPath not registered : " + qsXPathSelect);
  157 + }
  158 +
  159 + return qsXPath;
  160 +}
  161 +
  162 +QString DcXmlBase::evaluateXPath(const QString& qsXPathSelect,
  163 + const QList<QVariant>& arguments) const
  164 +{
  165 + QString qsResult = getXPath(qsXPathSelect);
  166 +
  167 + // LogInfo( "DcXmlBase::evaluateXPath", QString( "Found XPathExpression : " + qsResult + " for selection : " + qsXPathSelect ) );
  168 +
  169 + for (auto& value : arguments) {
  170 + qsResult = qsResult.arg(value.toString());
  171 + }
  172 +
  173 + // LogInfo( "DcXmlBase::evaluateXPath", QString( "Resulting XPathExpression : " + qsResult ) );
  174 + return qsResult;
  175 +}
  176 +
  177 +void DcXmlBase::setSimpleData(const QString& qsXPathSelect,
  178 + const QList<QVariant>& arguments,
  179 + const QVariant& data)
  180 +{
  181 + QString qsXPath = evaluateXPath(qsXPathSelect, arguments);
  182 + setNodeData(qsXPath, data);
  183 +}
  184 +
  185 +void DcXmlBase::setSimpleData(const QString& qsXPathSelect, const QVariant& data)
  186 +{
  187 + QString qsXPath = getXPath(qsXPathSelect);
  188 +
  189 + setNodeData(qsXPath, data);
  190 +}
  191 +
  192 +QVariant DcXmlBase::getSimpleData(const QString& qsXPathSelect,
  193 + const QList<QVariant>& arguments) const
  194 +{
  195 + QString qsXPath = evaluateXPath(qsXPathSelect, arguments);
  196 +
  197 + QVariant qvResult = getNodeData(qsXPath);
  198 +
  199 + return qvResult;
  200 +}
  201 +
  202 +// static
  203 +bool DcXmlBase::getBoolean(const QVariant& value)
  204 +{
  205 + bool b_result = false;
  206 +
  207 + QString l_result = value.toString().toUpper();
  208 + if ( // ------------------------
  209 + ("Y" == l_result) ||
  210 + ("YES" == l_result) ||
  211 + ("TRUE" == l_result) ||
  212 + ("ON" == l_result) ||
  213 + ("1" == l_result)
  214 + // ------------------------
  215 + ) {
  216 + b_result = true;
  217 + }
  218 +
  219 + return b_result;
  220 +}
  221 +
  222 +// static
  223 +QString DcXmlBase::getAttributeValue(const pugi::xml_node& xmlNode, const char* attributeName)
  224 +{
  225 + const auto attr = xmlNode.attribute(attributeName);
  226 + if (attr.empty()) {
  227 + return {};
  228 + }
  229 + return attr.value();
  230 +}
  231 +
  232 +pugi::xpath_node DcXmlBase::selectNode(const QString& qsXPath) const
  233 +{
  234 + return m_xmldoc.select_node(qsXPath.toStdString().c_str());
  235 +}
  236 +
  237 +QList<pugi::xpath_node> DcXmlBase::selectNodes(const QString& qsXPath) const
  238 +{
  239 + QList<pugi::xpath_node> lstResult;
  240 +
  241 + pugi::xpath_node_set nodes = m_xmldoc.select_nodes(qsXPath.toStdString().c_str());
  242 + for (auto& node : nodes) {
  243 + lstResult.append(node);
  244 + }
  245 +
  246 + return lstResult;
  247 +}
  248 +
  249 +void DcXmlBase::setNodeData(const QString& qsXPath, const QVariant& qsData)
  250 +{
  251 + pugi::xml_node selectedNode;
  252 + selectedNode = selectNode(qsXPath).node();
  253 +
  254 + if (!selectedNode.empty()) {
  255 + selectedNode.set_value(qsData.toString().toStdString().c_str());
  256 + }
  257 + else {
  258 + LogError("dcxml",
  259 + QString("No node(s) found for XPath expression : '%1'")
  260 + .arg(qsXPath));
  261 + }
  262 +}
  263 +
  264 +QVariant DcXmlBase::getNodeData(const QString& qsXPath) const
  265 +{
  266 + QVariant qvResult;
  267 + pugi::xml_node selectedNode = selectNode(qsXPath).node();
  268 + if (!selectedNode.empty()) {
  269 + qvResult = QString(selectedNode.value());
  270 + }
  271 + return qvResult;
  272 +}
  273 +
  274 +QString DcXmlBase::asString() const
  275 +{
  276 + xml_string_writer writer;
  277 + m_xmldoc.save(writer);
  278 +
  279 + return QString(writer.result.c_str());
  280 +}
src/dcxmlbase.h 0 โ†’ 100644
  1 +++ a/src/dcxmlbase.h
  1 +/* ****************************************************************************
  2 + * Copyright 2022 Open Systems Development BV *
  3 + * *
  4 + * Permission is hereby granted, free of charge, to any person obtaining a *
  5 + * copy of this software and associated documentation files (the "Software"), *
  6 + * to deal in the Software without restriction, including without limitation *
  7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, *
  8 + * and/or sell copies of the Software, and to permit persons to whom the *
  9 + * Software is furnished to do so, subject to the following conditions: *
  10 + * *
  11 + * The above copyright notice and this permission notice shall be included in *
  12 + * all copies or substantial portions of the Software. *
  13 + * *
  14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
  15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
  16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
  17 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
  18 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *
  19 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
  20 + * DEALINGS IN THE SOFTWARE. *
  21 + * ***************************************************************************/
  22 +
  23 +#pragma once
  24 +
  25 +#include <pugixml.hpp>
  26 +#include <string>
  27 +
  28 +#include <QtCore>
  29 +
  30 +namespace osdev {
  31 +namespace components {
  32 +namespace xml {
  33 +
  34 +/*!
  35 + * \brief xml_string_writer
  36 + * This struct is used to write a pugiXL DOM document to a std::string (QString)
  37 + * pugiXML is not able to this on its own, but we use the possibility to dump
  38 + * an XML-document to std::cout
  39 + */
  40 +struct xml_string_writer : pugi::xml_writer
  41 +{
  42 + std::string result = std::string();
  43 + virtual void write(const void* data, size_t size) override;
  44 +};
  45 +
  46 +/*!
  47 + * \brief The dcXmlBase class describes the base class for all xml related classes
  48 + * The basic functionality is implemented here. This class is intended to
  49 + * be inherited and specialized and not to be used directly. ( Nothing bad
  50 + * will happen, just to make life easier )
  51 + */
  52 +/*
  53 + * ________________________________________
  54 + * / I'm serious about thinking through all \
  55 + * | the possibilities before we settle on |
  56 + * | anything. All things have the |
  57 + * | advantages of their disadvantages, and |
  58 + * | vice versa. |
  59 + * | |
  60 + * | -- Larry Wall in |
  61 + * \ <199709032332.QAA21669@wall.org> /
  62 + * ----------------------------------------
  63 + * \
  64 + * \
  65 + * .--.
  66 + * |o_o |
  67 + * |:_/ |
  68 + * // \ \
  69 + * (| | )
  70 + * /'\_ _/`\
  71 + * \___)=(___/
  72 + */
  73 +
  74 +class DcXmlBase
  75 +{
  76 +public:
  77 + /*! Default constructor */
  78 + explicit DcXmlBase(const QString& xmlFile = QString());
  79 + virtual ~DcXmlBase();
  80 +
  81 + /*!
  82 + * \brief Parses the XML contents of the string.
  83 + * \param qsXml - String containing the contents of the XML-string
  84 + * \return true if successfull, false if not...
  85 + */
  86 + bool parseString(const QString& qsXml);
  87 +
  88 + /*!
  89 + * \brief Parses the contents of the given XML-file.
  90 + * \param qsXml - String with the filepath & -name of the XML file.
  91 + * \return true if successfull, false if not...
  92 + */
  93 + bool parseFile(const QString& qsXml);
  94 +
  95 + /*!
  96 + * \brief Adds an XPath expression to the internal structure.
  97 + * \param qsName - Name of the XPath expression. This should be descriptive to make life easier
  98 + * \param qsXPath - The XPath expression to the specific data we're interested in.
  99 + */
  100 + void addXPath(const QString& qsName, const QString& qsXPath);
  101 +
  102 + /*!
  103 + * \brief Retrieves an XPath expression from the internal structure
  104 + * \param qsXPathSelect - The name of the XPath expression.
  105 + * \return The XPath expression as stored in the internal Hash
  106 + */
  107 + QString getXPath(const QString& qsXPathSelect) const;
  108 +
  109 + /*!
  110 + * \brief Interprets the XPath expression and adds values to the variables.
  111 + * \param qsXPathSelect - The XPath expression as given by getXPath.
  112 + * \param arguments - The list of variables to be added to the XPath expression.
  113 + * \return The interpreted XPath expression.
  114 + */
  115 + QString evaluateXPath(const QString& qsXPathSelect, const QList<QVariant>& arguments) const;
  116 +
  117 + /*!
  118 + * \brief Set a simple node in the xml-doc.
  119 + * \param qsXPathSelect - The XPath expression of the node we want to set.
  120 + * \param arguments - the list of arguments in the node
  121 + * \param data - The nodetext.
  122 + */
  123 + void setSimpleData(const QString& qsXPathSelect, const QList<QVariant>& arguments, const QVariant& data);
  124 +
  125 + /*!
  126 + * \brief Set a simple node in the xml-doc.
  127 + * \param qsXPathSelect - The XPath expression of the node we want to set.
  128 + * \param data - The nodetext.
  129 + */
  130 + void setSimpleData(const QString& qsXPathSelect, const QVariant& data);
  131 +
  132 + QVariant getSimpleData(const QString& qsXPathSelect, const QList<QVariant>& arguments) const;
  133 +
  134 + /*!
  135 + * \brief Retreive a single node based on the XPath expression
  136 + * \param qsXPath - The XPath expression
  137 + * \return - a single xpath-node
  138 + */
  139 + pugi::xpath_node selectNode(const QString& qsXPath) const;
  140 +
  141 + /*!
  142 + * \brief Retreives a list of nodes based on the given XPath expression
  143 + * \param qsXPath - The XPath expression
  144 + * \return - The list of nodes
  145 + */
  146 + QList<pugi::xpath_node> selectNodes(const QString& qsXPath) const;
  147 +
  148 + /*! Added for convenience. The DOMTree is exported as QString */
  149 + QString asString() const;
  150 +
  151 + /*! Helper method for the setSimpleData */
  152 + void setNodeData(const QString& qsXPath, const QVariant& qsData);
  153 +
  154 + //! Helper method for the getSimpleData. Get data from the node that
  155 + //! is selected with the XPath expression.
  156 + virtual QVariant getNodeData(const QString& qsXPath) const;
  157 +
  158 + /**
  159 + * @brief Turns a value into a boolean.
  160 + * @param value Value to be interpreted.
  161 + * @return boolean representation of value
  162 + *
  163 + * The following (capitalised) items convert to "true" :
  164 + * - Y
  165 + * - YES
  166 + * - TRUE
  167 + * - ON
  168 + * - 1
  169 + *
  170 + * Everything else converts to false.
  171 + */
  172 + static bool getBoolean(const QVariant& value);
  173 +
  174 + /**
  175 + * @param xmlNode The node to query for an attribute value.
  176 + * @param attributeName The name of the attribute to query.
  177 + * @return an attribute value.
  178 + * @retval value as QString
  179 + * @retval null QString when the attribute is not found.
  180 + */
  181 + static QString getAttributeValue(const pugi::xml_node& xmlNode, const char* attributeName);
  182 +
  183 +private:
  184 + /*!
  185 + * \brief Translates the pugiXML status into Human Readable messages
  186 + * \param parseStatus - The pugi::XML status enum from the parser.
  187 + * \return True if there was no error whatsoever. False if not.. 8-|
  188 + */
  189 + bool checkError(pugi::xml_parse_status parseStatus);
  190 +
  191 + /*!
  192 + * \brief The internal representation of the XML document.
  193 + */
  194 + pugi::xml_document m_xmldoc;
  195 +
  196 + //! Storage for the XPath expressions
  197 + QHash<QString, QString> m_xPathHash;
  198 +};
  199 +
  200 +} // End namespace xml
  201 +} // End namespace osdev
  202 +} // End namespace components
  203 +