dcxmlbase.h 5.99 KB
#pragma once

#include <pugixml.hpp>
#include <string>

#include <QtCore>

namespace osdev {
namespace components {

/*!
 * \brief xml_string_writer
 *        This struct is used to write a pugiXL DOM document to a std::string
 *        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 std::string& xmlFile = std::string());
    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 std::string& 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 std::string& 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 std::string& qsName, const std::string& 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
     */
    std::string getXPath(const std::string& 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.
     */
    std::string evaluateXPath(const std::string& qsXPathSelect, const std::vector<QList<QVariant>>& 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 std::string& qsXPathSelect, const QList<QVariant>& 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 std::string& qsXPathSelect, const QVariant& data);

    QVariant getSimpleData(const std::string& qsXPathSelect, const QList<QVariant>& 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 std::string& qsXPath) const;

    /*!
     * \brief Retreives a list of nodes based on the given XPath expression
     * \param qsXPath     - The XPath expression
     * \return            - The list of nodes
     */
    std::vector<pugi::xpath_node> selectNodes(const std::string& qsXPath) const;

    /*! Added for convenience. The DOMTree is exported as std::string */
    std::string asString() const;

    /*! Helper method for the setSimpleData */
    void setNodeData(const std::string& 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 std::string& 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 std::string
     * @retval null std::string when the attribute is not found.
     */
    static std::string 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<std::string, std::string> m_xPathHash;
};

} // namespace osdev
} // namespace components