From f12cc09028e3b0b66251638ce9ad49362ba3a619 Mon Sep 17 00:00:00 2001 From: Peter M. Groen Date: Sun, 24 Jul 2022 16:40:59 +0200 Subject: [PATCH] Intermediate Commit --- src/CMakeLists.txt | 4 ++-- src/dcxmlbase.cpp | 280 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- src/dcxmlbase.h | 203 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- src/xmlbase.cpp | 280 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/xmlbase.h | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 375 insertions(+), 485 deletions(-) delete mode 100644 src/dcxmlbase.cpp delete mode 100644 src/dcxmlbase.h create mode 100644 src/xmlbase.cpp create mode 100644 src/xmlbase.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e614610..cf32182 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -16,8 +16,8 @@ include_directories( ) set(SRC_LIST - ${CMAKE_CURRENT_SOURCE_DIR}/dcxmlbase.h - ${CMAKE_CURRENT_SOURCE_DIR}/dcxmlbase.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/xmlbase.h + ${CMAKE_CURRENT_SOURCE_DIR}/xmlbase.cpp ) link_directories( diff --git a/src/dcxmlbase.cpp b/src/dcxmlbase.cpp deleted file mode 100644 index 8aa81fa..0000000 --- a/src/dcxmlbase.cpp +++ /dev/null @@ -1,280 +0,0 @@ -#include "dcxmlbase.h" -#include "log.h" - -/* - * ________________________________________ - * / Distance doesn't make you any smaller, \ - * | but it does make you part of a larger | - * \ picture. / - * ---------------------------------------- - * \ - * \ - * .--. - * |o_o | - * |:_/ | - * // \ \ - * (| | ) - * /'\_ _/`\ - * \___)=(___/ - * - **********************************************************/ - -using namespace osdev::components::xml; -using namespace osdev::components::log; - -void xml_string_writer::write(const void* data, size_t size) -{ - result += std::string(static_cast(data), size); -} - -DcXmlBase::DcXmlBase(const QString& xmlFile) - : m_xmldoc() - , m_xPathHash() -{ - if (!xmlFile.isNull() || !xmlFile.isEmpty()) { - if (parseFile(xmlFile)) { - LogDebug("[DcXmlBase::DcXmlBase]", QString("File : %1 ..............[OK].").arg(xmlFile).toStdString()); - } - else { - LogError("[DcXmlBase::DcXmlBase]", QString("File : %1 ..............[Failed].").arg(xmlFile).toStdString()); - throw std::runtime_error("[DcXmlBase::DcXmlBase] parseFile failed"); - } - } -} - -DcXmlBase::~DcXmlBase() = default; - -bool DcXmlBase::parseString(const QString& qsXml) -{ - bool bResult = false; - - if (!qsXml.isEmpty()) { - pugi::xml_parse_status parseStatus = m_xmldoc.load_buffer(qsXml.toStdString().c_str(), - qsXml.toStdString().size()) - .status; - bResult = checkError(parseStatus); - } - - return bResult; -} - -bool DcXmlBase::parseFile(const QString& qsXml) -{ - bool bResult = false; - - if (!qsXml.isEmpty()) { - pugi::xml_parse_status parseStatus = m_xmldoc.load_file(qsXml.toStdString().c_str()).status; - bResult = checkError(parseStatus); - } - - return bResult; -} - -bool DcXmlBase::checkError(pugi::xml_parse_status _parseStatus) -{ - bool bResult = false; - QString sLogMessage = "An unknown error occured."; - -/* -* GCC 5.3.1 insits on all enumeration cases for this switch to be specified. -* The enumeration cases that throws -Wswitch warning are not available in pugixml for FC21. -* For backward compatibility with older pugixml version "-Wswitch" warnings are temporarily supressed. -*/ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wswitch" - switch (_parseStatus) { - case pugi::status_ok: - sLogMessage = "File parsed successfully."; - bResult = true; - break; - case pugi::status_file_not_found: - sLogMessage = "File not found."; - break; - case pugi::status_io_error: - sLogMessage = "Some I/O Error occured during reading the file / stream. Check the hardware for errors."; - break; - case pugi::status_out_of_memory: - sLogMessage = "Out of Memory while parsing the file."; - break; - case pugi::status_internal_error: - sLogMessage = "Oh dear... That's different. Something went horribly wrong. It is unrecoverable. We're exiting the whole shabang.."; - break; - case pugi::status_unrecognized_tag: - sLogMessage = "Parsing stopping due to a tag with either an empty name or a name which starts with an incorrect character (Left a '#' somewhere?)"; - break; - case pugi::status_bad_pi: - sLogMessage = "Parsing stopped due to incorrect document declaration/processing instruction. "; - break; - case pugi::status_bad_comment: - sLogMessage = "Parsing stopped due to the invalid construct of a Comment."; - break; - case pugi::status_bad_cdata: - sLogMessage = "Parsing stopped due to the invalid construct of a CDATA section."; - break; - case pugi::status_bad_doctype: - sLogMessage = "Parsing stopped due to the invalid construct of a DocType."; - break; - case pugi::status_bad_pcdata: - sLogMessage = "Parsing stopped due to the invalid construct of a PCDATA section."; - break; - case pugi::status_bad_attribute: - sLogMessage = "Parsing stopped because there was an incorrect attribute, such as an attribute without value or with value that is not quoted (note that is incorrect in XML)."; - break; - case pugi::status_bad_start_element: - sLogMessage = "Parsing stopped because a starting tag either had no closing > symbol or contained some incorrect symbol."; - break; - case pugi::status_bad_end_element: - sLogMessage = "Parsing stopped because ending tag had incorrect syntax (i.e. extra non-whitespace symbols between tag name and >)."; - break; - case pugi::status_end_element_mismatch: - sLogMessage = "parsing stopped because the closing tag did not match the opening one (i.e. ) or because some tag was not closed at all."; - break; - // DISABLED ON FEDORA 21 and CentOS 7. Not present in pugixml 1.0-8.fc21 - // case pugi::status_append_invalid_root: - // case pugi::status_no_document_element: - } -#pragma GCC diagnostic pop - LogDebug("[DcXmlBase::checkError]", sLogMessage.toStdString()); - return bResult; -} - -void DcXmlBase::addXPath(const QString& qsName, const QString& qsXPath) -{ - if (m_xPathHash.contains(qsName)) { - LogWarning("[DcXmlBase::addXPath]", std::string( "XPath already registered : " + qsName.toStdString())); - } - m_xPathHash.insert(qsName, qsXPath); - - LogDebug("[DcXmlBase::addXPath]", std::string("XPath" + qsXPath.toStdString() + " registered with key : " + qsName.toStdString())); -} - -QString DcXmlBase::getXPath(const QString& qsXPathSelect) const -{ - QString qsXPath = m_xPathHash.value(qsXPathSelect); - - if (qsXPath.isEmpty()) { - LogWarning("dcxml", "XPath not registered : " + qsXPathSelect); - } - - return qsXPath; -} - -QString DcXmlBase::evaluateXPath(const QString& qsXPathSelect, - const QList& arguments) const -{ - QString qsResult = getXPath(qsXPathSelect); - - // LogInfo( "DcXmlBase::evaluateXPath", QString( "Found XPathExpression : " + qsResult + " for selection : " + qsXPathSelect ) ); - - for (auto& value : arguments) { - qsResult = qsResult.arg(value.toString()); - } - - // LogInfo( "DcXmlBase::evaluateXPath", QString( "Resulting XPathExpression : " + qsResult ) ); - return qsResult; -} - -void DcXmlBase::setSimpleData(const QString& qsXPathSelect, - const QList& arguments, - const QVariant& data) -{ - QString qsXPath = evaluateXPath(qsXPathSelect, arguments); - setNodeData(qsXPath, data); -} - -void DcXmlBase::setSimpleData(const QString& qsXPathSelect, const QVariant& data) -{ - QString qsXPath = getXPath(qsXPathSelect); - - setNodeData(qsXPath, data); -} - -QVariant DcXmlBase::getSimpleData(const QString& qsXPathSelect, - const QList& arguments) const -{ - QString qsXPath = evaluateXPath(qsXPathSelect, arguments); - - QVariant qvResult = getNodeData(qsXPath); - - return qvResult; -} - -// static -bool DcXmlBase::getBoolean(const QVariant& value) -{ - bool b_result = false; - - QString l_result = value.toString().toUpper(); - if ( // ------------------------ - ("Y" == l_result) || - ("YES" == l_result) || - ("TRUE" == l_result) || - ("ON" == l_result) || - ("1" == l_result) - // ------------------------ - ) { - b_result = true; - } - - return b_result; -} - -// static -QString DcXmlBase::getAttributeValue(const pugi::xml_node& xmlNode, const char* attributeName) -{ - const auto attr = xmlNode.attribute(attributeName); - if (attr.empty()) { - return {}; - } - return attr.value(); -} - -pugi::xpath_node DcXmlBase::selectNode(const QString& qsXPath) const -{ - return m_xmldoc.select_node(qsXPath.toStdString().c_str()); -} - -QList DcXmlBase::selectNodes(const QString& qsXPath) const -{ - QList lstResult; - - pugi::xpath_node_set nodes = m_xmldoc.select_nodes(qsXPath.toStdString().c_str()); - for (auto& node : nodes) { - lstResult.append(node); - } - - return lstResult; -} - -void DcXmlBase::setNodeData(const QString& qsXPath, const QVariant& qsData) -{ - pugi::xml_node selectedNode; - selectedNode = selectNode(qsXPath).node(); - - if (!selectedNode.empty()) { - selectedNode.set_value(qsData.toString().toStdString().c_str()); - } - else { - LogError("dcxml", - QString("No node(s) found for XPath expression : '%1'") - .arg(qsXPath)); - } -} - -QVariant DcXmlBase::getNodeData(const QString& qsXPath) const -{ - QVariant qvResult; - pugi::xml_node selectedNode = selectNode(qsXPath).node(); - if (!selectedNode.empty()) { - qvResult = QString(selectedNode.value()); - } - return qvResult; -} - -QString DcXmlBase::asString() const -{ - xml_string_writer writer; - m_xmldoc.save(writer); - - return QString(writer.result.c_str()); -} diff --git a/src/dcxmlbase.h b/src/dcxmlbase.h deleted file mode 100644 index beba9bc..0000000 --- a/src/dcxmlbase.h +++ /dev/null @@ -1,203 +0,0 @@ -/* **************************************************************************** - * Copyright 2022 Open Systems Development BV * - * * - * Permission is hereby granted, free of charge, to any person obtaining a * - * copy of this software and associated documentation files (the "Software"), * - * to deal in the Software without restriction, including without limitation * - * the rights to use, copy, modify, merge, publish, distribute, sublicense, * - * and/or sell copies of the Software, and to permit persons to whom the * - * Software is furnished to do so, subject to the following conditions: * - * * - * The above copyright notice and this permission notice shall be included in * - * all copies or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * - * DEALINGS IN THE SOFTWARE. * - * ***************************************************************************/ - -#pragma once - -#include -#include - -#include - -namespace osdev { -namespace components { -namespace xml { - -/*! - * \brief xml_string_writer - * This struct is used to write a pugiXL DOM document to a std::string (QString) - * pugiXML is not able to this on its own, but we use the possibility to dump - * an XML-document to std::cout - */ -struct xml_string_writer : pugi::xml_writer -{ - std::string result = std::string(); - virtual void write(const void* data, size_t size) override; -}; - -/*! - * \brief The dcXmlBase class describes the base class for all xml related classes - * The basic functionality is implemented here. This class is intended to - * be inherited and specialized and not to be used directly. ( Nothing bad - * will happen, just to make life easier ) - */ -/* - * ________________________________________ - * / I'm serious about thinking through all \ - * | the possibilities before we settle on | - * | anything. All things have the | - * | advantages of their disadvantages, and | - * | vice versa. | - * | | - * | -- Larry Wall in | - * \ <199709032332.QAA21669@wall.org> / - * ---------------------------------------- - * \ - * \ - * .--. - * |o_o | - * |:_/ | - * // \ \ - * (| | ) - * /'\_ _/`\ - * \___)=(___/ - */ - -class DcXmlBase -{ -public: - /*! Default constructor */ - explicit DcXmlBase(const QString& xmlFile = QString()); - virtual ~DcXmlBase(); - - /*! - * \brief Parses the XML contents of the string. - * \param qsXml - String containing the contents of the XML-string - * \return true if successfull, false if not... - */ - bool parseString(const QString& qsXml); - - /*! - * \brief Parses the contents of the given XML-file. - * \param qsXml - String with the filepath & -name of the XML file. - * \return true if successfull, false if not... - */ - bool parseFile(const QString& qsXml); - - /*! - * \brief Adds an XPath expression to the internal structure. - * \param qsName - Name of the XPath expression. This should be descriptive to make life easier - * \param qsXPath - The XPath expression to the specific data we're interested in. - */ - void addXPath(const QString& qsName, const QString& qsXPath); - - /*! - * \brief Retrieves an XPath expression from the internal structure - * \param qsXPathSelect - The name of the XPath expression. - * \return The XPath expression as stored in the internal Hash - */ - QString getXPath(const QString& qsXPathSelect) const; - - /*! - * \brief Interprets the XPath expression and adds values to the variables. - * \param qsXPathSelect - The XPath expression as given by getXPath. - * \param arguments - The list of variables to be added to the XPath expression. - * \return The interpreted XPath expression. - */ - QString evaluateXPath(const QString& qsXPathSelect, const QList& arguments) const; - - /*! - * \brief Set a simple node in the xml-doc. - * \param qsXPathSelect - The XPath expression of the node we want to set. - * \param arguments - the list of arguments in the node - * \param data - The nodetext. - */ - void setSimpleData(const QString& qsXPathSelect, const QList& arguments, const QVariant& data); - - /*! - * \brief Set a simple node in the xml-doc. - * \param qsXPathSelect - The XPath expression of the node we want to set. - * \param data - The nodetext. - */ - void setSimpleData(const QString& qsXPathSelect, const QVariant& data); - - QVariant getSimpleData(const QString& qsXPathSelect, const QList& arguments) const; - - /*! - * \brief Retreive a single node based on the XPath expression - * \param qsXPath - The XPath expression - * \return - a single xpath-node - */ - pugi::xpath_node selectNode(const QString& qsXPath) const; - - /*! - * \brief Retreives a list of nodes based on the given XPath expression - * \param qsXPath - The XPath expression - * \return - The list of nodes - */ - QList selectNodes(const QString& qsXPath) const; - - /*! Added for convenience. The DOMTree is exported as QString */ - QString asString() const; - - /*! Helper method for the setSimpleData */ - void setNodeData(const QString& qsXPath, const QVariant& qsData); - - //! Helper method for the getSimpleData. Get data from the node that - //! is selected with the XPath expression. - virtual QVariant getNodeData(const QString& qsXPath) const; - - /** - * @brief Turns a value into a boolean. - * @param value Value to be interpreted. - * @return boolean representation of value - * - * The following (capitalised) items convert to "true" : - * - Y - * - YES - * - TRUE - * - ON - * - 1 - * - * Everything else converts to false. - */ - static bool getBoolean(const QVariant& value); - - /** - * @param xmlNode The node to query for an attribute value. - * @param attributeName The name of the attribute to query. - * @return an attribute value. - * @retval value as QString - * @retval null QString when the attribute is not found. - */ - static QString getAttributeValue(const pugi::xml_node& xmlNode, const char* attributeName); - -private: - /*! - * \brief Translates the pugiXML status into Human Readable messages - * \param parseStatus - The pugi::XML status enum from the parser. - * \return True if there was no error whatsoever. False if not.. 8-| - */ - bool checkError(pugi::xml_parse_status parseStatus); - - /*! - * \brief The internal representation of the XML document. - */ - pugi::xml_document m_xmldoc; - - //! Storage for the XPath expressions - QHash m_xPathHash; -}; - -} // End namespace xml -} // End namespace osdev -} // End namespace components - diff --git a/src/xmlbase.cpp b/src/xmlbase.cpp new file mode 100644 index 0000000..8aa81fa --- /dev/null +++ b/src/xmlbase.cpp @@ -0,0 +1,280 @@ +#include "dcxmlbase.h" +#include "log.h" + +/* + * ________________________________________ + * / Distance doesn't make you any smaller, \ + * | but it does make you part of a larger | + * \ picture. / + * ---------------------------------------- + * \ + * \ + * .--. + * |o_o | + * |:_/ | + * // \ \ + * (| | ) + * /'\_ _/`\ + * \___)=(___/ + * + **********************************************************/ + +using namespace osdev::components::xml; +using namespace osdev::components::log; + +void xml_string_writer::write(const void* data, size_t size) +{ + result += std::string(static_cast(data), size); +} + +DcXmlBase::DcXmlBase(const QString& xmlFile) + : m_xmldoc() + , m_xPathHash() +{ + if (!xmlFile.isNull() || !xmlFile.isEmpty()) { + if (parseFile(xmlFile)) { + LogDebug("[DcXmlBase::DcXmlBase]", QString("File : %1 ..............[OK].").arg(xmlFile).toStdString()); + } + else { + LogError("[DcXmlBase::DcXmlBase]", QString("File : %1 ..............[Failed].").arg(xmlFile).toStdString()); + throw std::runtime_error("[DcXmlBase::DcXmlBase] parseFile failed"); + } + } +} + +DcXmlBase::~DcXmlBase() = default; + +bool DcXmlBase::parseString(const QString& qsXml) +{ + bool bResult = false; + + if (!qsXml.isEmpty()) { + pugi::xml_parse_status parseStatus = m_xmldoc.load_buffer(qsXml.toStdString().c_str(), + qsXml.toStdString().size()) + .status; + bResult = checkError(parseStatus); + } + + return bResult; +} + +bool DcXmlBase::parseFile(const QString& qsXml) +{ + bool bResult = false; + + if (!qsXml.isEmpty()) { + pugi::xml_parse_status parseStatus = m_xmldoc.load_file(qsXml.toStdString().c_str()).status; + bResult = checkError(parseStatus); + } + + return bResult; +} + +bool DcXmlBase::checkError(pugi::xml_parse_status _parseStatus) +{ + bool bResult = false; + QString sLogMessage = "An unknown error occured."; + +/* +* GCC 5.3.1 insits on all enumeration cases for this switch to be specified. +* The enumeration cases that throws -Wswitch warning are not available in pugixml for FC21. +* For backward compatibility with older pugixml version "-Wswitch" warnings are temporarily supressed. +*/ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wswitch" + switch (_parseStatus) { + case pugi::status_ok: + sLogMessage = "File parsed successfully."; + bResult = true; + break; + case pugi::status_file_not_found: + sLogMessage = "File not found."; + break; + case pugi::status_io_error: + sLogMessage = "Some I/O Error occured during reading the file / stream. Check the hardware for errors."; + break; + case pugi::status_out_of_memory: + sLogMessage = "Out of Memory while parsing the file."; + break; + case pugi::status_internal_error: + sLogMessage = "Oh dear... That's different. Something went horribly wrong. It is unrecoverable. We're exiting the whole shabang.."; + break; + case pugi::status_unrecognized_tag: + sLogMessage = "Parsing stopping due to a tag with either an empty name or a name which starts with an incorrect character (Left a '#' somewhere?)"; + break; + case pugi::status_bad_pi: + sLogMessage = "Parsing stopped due to incorrect document declaration/processing instruction. "; + break; + case pugi::status_bad_comment: + sLogMessage = "Parsing stopped due to the invalid construct of a Comment."; + break; + case pugi::status_bad_cdata: + sLogMessage = "Parsing stopped due to the invalid construct of a CDATA section."; + break; + case pugi::status_bad_doctype: + sLogMessage = "Parsing stopped due to the invalid construct of a DocType."; + break; + case pugi::status_bad_pcdata: + sLogMessage = "Parsing stopped due to the invalid construct of a PCDATA section."; + break; + case pugi::status_bad_attribute: + sLogMessage = "Parsing stopped because there was an incorrect attribute, such as an attribute without value or with value that is not quoted (note that is incorrect in XML)."; + break; + case pugi::status_bad_start_element: + sLogMessage = "Parsing stopped because a starting tag either had no closing > symbol or contained some incorrect symbol."; + break; + case pugi::status_bad_end_element: + sLogMessage = "Parsing stopped because ending tag had incorrect syntax (i.e. extra non-whitespace symbols between tag name and >)."; + break; + case pugi::status_end_element_mismatch: + sLogMessage = "parsing stopped because the closing tag did not match the opening one (i.e. ) or because some tag was not closed at all."; + break; + // DISABLED ON FEDORA 21 and CentOS 7. Not present in pugixml 1.0-8.fc21 + // case pugi::status_append_invalid_root: + // case pugi::status_no_document_element: + } +#pragma GCC diagnostic pop + LogDebug("[DcXmlBase::checkError]", sLogMessage.toStdString()); + return bResult; +} + +void DcXmlBase::addXPath(const QString& qsName, const QString& qsXPath) +{ + if (m_xPathHash.contains(qsName)) { + LogWarning("[DcXmlBase::addXPath]", std::string( "XPath already registered : " + qsName.toStdString())); + } + m_xPathHash.insert(qsName, qsXPath); + + LogDebug("[DcXmlBase::addXPath]", std::string("XPath" + qsXPath.toStdString() + " registered with key : " + qsName.toStdString())); +} + +QString DcXmlBase::getXPath(const QString& qsXPathSelect) const +{ + QString qsXPath = m_xPathHash.value(qsXPathSelect); + + if (qsXPath.isEmpty()) { + LogWarning("dcxml", "XPath not registered : " + qsXPathSelect); + } + + return qsXPath; +} + +QString DcXmlBase::evaluateXPath(const QString& qsXPathSelect, + const QList& arguments) const +{ + QString qsResult = getXPath(qsXPathSelect); + + // LogInfo( "DcXmlBase::evaluateXPath", QString( "Found XPathExpression : " + qsResult + " for selection : " + qsXPathSelect ) ); + + for (auto& value : arguments) { + qsResult = qsResult.arg(value.toString()); + } + + // LogInfo( "DcXmlBase::evaluateXPath", QString( "Resulting XPathExpression : " + qsResult ) ); + return qsResult; +} + +void DcXmlBase::setSimpleData(const QString& qsXPathSelect, + const QList& arguments, + const QVariant& data) +{ + QString qsXPath = evaluateXPath(qsXPathSelect, arguments); + setNodeData(qsXPath, data); +} + +void DcXmlBase::setSimpleData(const QString& qsXPathSelect, const QVariant& data) +{ + QString qsXPath = getXPath(qsXPathSelect); + + setNodeData(qsXPath, data); +} + +QVariant DcXmlBase::getSimpleData(const QString& qsXPathSelect, + const QList& arguments) const +{ + QString qsXPath = evaluateXPath(qsXPathSelect, arguments); + + QVariant qvResult = getNodeData(qsXPath); + + return qvResult; +} + +// static +bool DcXmlBase::getBoolean(const QVariant& value) +{ + bool b_result = false; + + QString l_result = value.toString().toUpper(); + if ( // ------------------------ + ("Y" == l_result) || + ("YES" == l_result) || + ("TRUE" == l_result) || + ("ON" == l_result) || + ("1" == l_result) + // ------------------------ + ) { + b_result = true; + } + + return b_result; +} + +// static +QString DcXmlBase::getAttributeValue(const pugi::xml_node& xmlNode, const char* attributeName) +{ + const auto attr = xmlNode.attribute(attributeName); + if (attr.empty()) { + return {}; + } + return attr.value(); +} + +pugi::xpath_node DcXmlBase::selectNode(const QString& qsXPath) const +{ + return m_xmldoc.select_node(qsXPath.toStdString().c_str()); +} + +QList DcXmlBase::selectNodes(const QString& qsXPath) const +{ + QList lstResult; + + pugi::xpath_node_set nodes = m_xmldoc.select_nodes(qsXPath.toStdString().c_str()); + for (auto& node : nodes) { + lstResult.append(node); + } + + return lstResult; +} + +void DcXmlBase::setNodeData(const QString& qsXPath, const QVariant& qsData) +{ + pugi::xml_node selectedNode; + selectedNode = selectNode(qsXPath).node(); + + if (!selectedNode.empty()) { + selectedNode.set_value(qsData.toString().toStdString().c_str()); + } + else { + LogError("dcxml", + QString("No node(s) found for XPath expression : '%1'") + .arg(qsXPath)); + } +} + +QVariant DcXmlBase::getNodeData(const QString& qsXPath) const +{ + QVariant qvResult; + pugi::xml_node selectedNode = selectNode(qsXPath).node(); + if (!selectedNode.empty()) { + qvResult = QString(selectedNode.value()); + } + return qvResult; +} + +QString DcXmlBase::asString() const +{ + xml_string_writer writer; + m_xmldoc.save(writer); + + return QString(writer.result.c_str()); +} diff --git a/src/xmlbase.h b/src/xmlbase.h new file mode 100644 index 0000000..99949fd --- /dev/null +++ b/src/xmlbase.h @@ -0,0 +1,93 @@ +/* **************************************************************************** + * Copyright 2022 Open Systems Development BV * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the "Software"), * + * to deal in the Software without restriction, including without limitation * + * the rights to use, copy, modify, merge, publish, distribute, sublicense, * + * and/or sell copies of the Software, and to permit persons to whom the * + * Software is furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included in * + * all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * + * DEALINGS IN THE SOFTWARE. * + * ***************************************************************************/ + +#pragma once + +#include +#include +#include +#include + +namespace osdev { +namespace components { +namespace xml { + +/*! + * \brief xml_string_writer + * This struct is used to write a pugixml DOM document to a std::string. + * pugiXML is not able to do this on its own, but we use the possibility + * to dump an xml-document to std::cout. + */ +struct xml_string_writer : pugi::xml_writer +{ + std::string result = std::string(); + virtual void write(const void* data, size_t size) override; +}; + +/*! + * \brief The XmlBase class describes the base class for all xml related classes. + * The basic functionality is implemented here. This class is intrended to + * be inherited an d specialized and not to be used directly. ( Nothing bad + * will happen, just to make life easier. ) + */ +class XmlBase +{ +public: + /*! Default constructor */ + explicit XmlBase(const std::string xmlFile = std::string() ); + virtual ~XmlBase(); + + /*! + * \brief Parses the xml contents of the string. + * \param sxml - String containing the xml-string + * \return true if succesful, false if not... + */ + bool parseString(const std::string &sxml); + + /*! + * \brief Parses the contents of the givenm XML-file. + * \param sxml - String with the filepath & -name of the xml file. + * \return true if succesfull, false if not. + */ + bool parseFile(const std::string sxml); + + /*! + * \brief Adds and XPath expression to the internal structure. + * \param sName - Name of the XPath expression. This should be descriptive to make life easier. + * \param sXPath - The XPath expression to the specific data we're interested in. + */ + void addXPath(const std::string &sName, const std::string &sXPath); + + /*! + * \brief Retrieves an XPatrh expression from the internal structure + * \param sXpathSelect - The name of the XPath expression + * \return The XPath expression as stored in the internal Hash. + */ + std::string getXPath(const std::string &sXpathSelect); + + +}; + + +} // End namespace xml +} // End namespace components +} // End namespace osdev -- libgit2 0.21.4