/*************************************************************************** * GXml.hpp - XML class * * ----------------------------------------------------------------------- * * copyright (C) 2010-2016 by Juergen Knoedlseder * * ----------------------------------------------------------------------- * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation, either version 3 of the License, or * * (at your option) any later version. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * * * ***************************************************************************/ /** * @file GXml.hpp * @brief XML class interface definition * @author Juergen Knoedlseder */ #ifndef GXML_HPP #define GXML_HPP /* __ Includes ___________________________________________________________ */ #include #include "GContainer.hpp" #include "GUrl.hpp" #include "GXmlNode.hpp" #include "GXmlDocument.hpp" #include "GXmlElement.hpp" #include "GXmlText.hpp" /* __ Forward declarations _______________________________________________ */ class GFilename; /***********************************************************************//** * @class GXml * * @brief XML class * * This class holds the content of an Extensible Markup Language (XML) * document. An XML document is composed of a list of nodes, each of which * may contain lists of nodes, which again can contain list of nodes and so * on. This produces a tree made of nodes with an arbitrary complexity. * Nodes that do not contain any further nodes are the endpoints of the tree * that are called leafs. * * An example of an XML document is shown below * * * * * * * * This is a text * 17 * * * * An XML document is a plain ASCII file. Every XML document begins by a * declaration of the XML version and an optional information about the * encoding of the text. * * The XML document is structured using @b tags. A tag is a markup construct * that begins with @< and ends with @>. Tags come in three flavors: * - start-tags; for example: @ * - end-tags; for example: @ * - empty-element tags; for example: @ * * The header line of an XML document is an empty-element tag. Each tag may * contain an arbitrary number of @b attributes of the form * * version="1.0" * * Alternative quotes ' are also allowed. * * A logical document component which either begins with a start-tag and ends * with a matching end-tag or consists only of an empty-element tag is called * an @b element. The characters between the start- and end-tags, if any, are * the element's content, and may contain markup, including other elements, * which are called @b child @b elements. An example of an element is * * * This is a text * * Another is * * * * This last example has two attributes. The first word in an element is * called the @b element @b name. Every element has a name. Elements can * therefore be accessed by name, however, several elements with the same * name may exist. * * GammaLib implements the XML document in form of a master class GXml * which contains the root node of the document. The root node is * realized by the GXmlDocument class. GXmlDocument derives from GXmlNode, * which defines the abstract interface for all XML nodes. The following * XML nodes exist: * - GXmlElement: implements an element * - GXmlText: implements a text leaf * - GXmlPI: implements a Processing Instruction * - GXmlComment: implement a comment * * XML element attributes are implemented using GXmlAttribute. * * The GXml class provides methods to access the nodes of the XML document, * and to load and save the document from a URL. GXml derives from GContainer * as it behaves like a container class. It does, however, not contain an * explicit list, as the only data member of the class is a single instance * of GXmlDocument. GXmlDocument contains the hierarchical list of all XML * nodes. * * To manipulate the child nodes of GXmlDocument, the usual container class * methods are available. size() returns the number of child nodes that * exist in the XML document root (in the above example there would be two * child elements with name @p element). The child nodes are accessed using * the operator[]. The is_empty() method checks whether the document root has * no children. * * The set() method allows to set a specific child node, the append() method * appends a child node to the XML document root. There is a second variant * of the append() method that appends a element of type GXmlElement to the * XML document root and that returns a pointer to this element. As argument, * this second method takes a text string that defines the element name and * attributes. For example, the first node in the above example could have * been generated using * * GXml xml; * xml.append("element type=\"Measurement\""); * * Note that the @< and @> symbols are not part of the text string that is * passed to the append() method. * * The insert() method inserts a child node at the specified index in the * XML root document. The remove() method removes the child node at the * specified index from the document root. The reserve() method reserves * space for a specified number of child nodes in the XML document root. * And the extend() method appends all child nodes that are found in the * specified argument to the XML document root. * * Most of the nodes encountered in a XML document will be @b element * @b nodes, hence special methods for handling element nodes have been * implemented. The elements() method returns the number of child elements * that are present in the XML document root. A variant that takes a string * argument counts the number of child elements with a given name. The * element() method allows to access the child elements. There are again * two flavours, one that simply takes an index to loop over all child * elements, and another that takes a name and a index to loop over all * child elements of a given name. For element access, non-const and const * variants exist. * * Finally, the load() and save() methods enable loading and saving a XML * document from and to disk. The read() and write() method, which do the * actual job of reading and writing, operate on general Unified Resource * Locators, so that XML documents can also through other media than flat * files. * * The print() method does not print the full XML document into a string * but shows a concise summary that reflects the tree structure. For writing * the document in a string, use the write() method to write in a string URL * object (GUrlString). ***************************************************************************/ class GXml : public GContainer { // Friend classes friend class GXmlNode; friend class GXmlDocument; friend class GXmlText; public: // Constructors and destructors GXml(void); GXml(const GXml& xml); explicit GXml(const std::string& xml); virtual ~GXml(void); // Operators GXml& operator=(const GXml& xml); GXmlNode* operator[](const int& index); const GXmlNode* operator[](const int& index) const; // Methods void clear(void); GXml* clone(void) const; std::string classname(void) const; int size(void) const; bool is_empty(void) const; GXmlNode* set(const int& index, const GXmlNode& node); GXmlNode* append(const GXmlNode& node); GXmlElement* append(const std::string& segment); GXmlNode* insert(const int& index, const GXmlNode& node); void remove(const int& index); void reserve(const int& num); void extend(const GXmlNode& node); int elements(void) const; int elements(const std::string& name) const; GXmlElement* element(const int& index); const GXmlElement* element(const int& index) const; GXmlElement* element(const std::string& name); const GXmlElement* element(const std::string& name) const; GXmlElement* element(const std::string& name, const int& index); const GXmlElement* element(const std::string& name, const int& index) const; void load(const GFilename& filename); void save(const GFilename& filename) const; void read(const GUrl& url); void write(GUrl& url, const int& indent = 0) const; std::string print(const GChatter& chatter = NORMAL) const; std::string print(const GChatter& chatter = NORMAL, const int& indent = 0) const; protected: // Protected enumerators enum MarkupType { MT_ELEMENT_START, MT_ELEMENT_END, MT_ELEMENT_EMPTY, MT_COMMENT, MT_DECLARATION, MT_PROCESSING, MT_INVALID }; // Protected methods void init_members(void); void copy_members(const GXml& xml); void free_members(void); void parse(const GUrl& url); void process_markup(GXmlNode** current, const std::string& segment); void process_text(GXmlNode** current, const std::string& segment); MarkupType get_markuptype(const std::string& segment) const; // Protected members GXmlDocument m_root; //!< Root document node }; /***********************************************************************//** * @brief Return class name * * @return String containing the class name ("GXml"). ***************************************************************************/ inline std::string GXml::classname(void) const { return ("GXml"); } /***********************************************************************//** * @brief Return number of child nodes * * @return Number of child nodes in node. ***************************************************************************/ inline int GXml::size(void) const { return m_root.size(); } /***********************************************************************//** * @brief Signals if document has no child nodes * * @return True if document has no child nodes. ***************************************************************************/ inline bool GXml::is_empty(void) const { return m_root.is_empty(); } #endif /* GXML_HPP */