/* Ousía Copyright (C) 2014 Benjamin Paaßen, Andreas Stöckel 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 XML.hpp * * This header provides XML classes to build an XML tree as well as functions * to serialize that XMl tree to text. We do not support the full XML * specification (like described here: http://www.w3.org/TR/REC-xml/ ) but only * a small subset. This subset is defined by the following context-free grammar: * * NODE := ELEMENT | string * ELEMENT := START NODES END * NODES := NODE NODES | epsilon * START := < name ATTRIBUTES > * ATTRIBUTES := ATTRIBUTE ATTRIBUTES | epsilon * ATTRIBUTE := key = "value" * END := * * where the Axiom of a document is "Element". Note that we accept only a * singular root element and no primitive text at root level. Attributes are * key-value pairs of strings. Start and end tag name have to match. * * @author Benjamin Paaßen (bpaassen@techfak.uni-bielefeld.de) */ #ifndef _OUSIA_XML_HPP_ #define _OUSIA_XML_HPP_ #include #include #include #include #include namespace ousia { // Forward declarations class RttiType; template class Rtti; namespace xml { class Element; /** * Node is the common super-class of actual elements (tag-bounded) and text. * It specifies the pure virtual serialize() function that the subclasses * implement. */ class Node : public Managed { private: Owned parent; public: Node(Manager &mgr, Handle parent) : Managed(mgr), parent(acquire(parent)){}; /** * This method writes an XML doctype and the XML representing the current * node, including all children, to the given output stream. * @param out is the output stream the serialized data shall be * written to. * @param doctype enables you to add a prefix specifying the doctype. * @param pretty is a flag that manipulates whether newlines and tabs are * used. */ void serialize(std::ostream &out, const std::string &doctype = "", bool pretty = true); /** * This method just writes the XML representation of this node to the * output stream. * * @param out the output stream the serialized data shall be written * to. * @param tabdepth the current tabdepth for prettier output. * @param pretty is a flag that manipulates whether newlines and tabs are * used. */ virtual void doSerialize(std::ostream &out, unsigned int tabdepth, bool pretty) = 0; /** * @return the parent XML element of this node. */ Rooted getParent() const { return parent; } }; /** * An element in XML is defined as by the W3C: * * http://www.w3.org/TR/REC-xml/#sec-starttags * * For as an element necessarily has a name. It may have key-value pairs as * attributes, where each key is unique (which is enforced by std::map). * Additionally it might have other Nodes as children. */ class Element : public Node { private: ManagedVector children; public: const std::string name; std::map attributes; Element(Manager &mgr, Handle parent, std::string name) : Node(mgr, parent), children(this), name(std::move(name)) { } Element(Manager &mgr, Handle parent, std::string name, std::map attributes) : Node(mgr, parent), children(this), name(std::move(name)), attributes(std::move(attributes)) { } /** * This writes the following to the output stream: * * The start tag of this element including name and attributes * * The serialized data of all children as ordered by the vector. * * The end tag of this element. * */ void doSerialize(std::ostream &out, unsigned int tabdepth, bool pretty) override; const ManagedVector &getChildren() const { return children; } void addChild(Handle child) { children.push_back(child); } void addChildren(std::vector> c) { children.insert(children.end(), c.begin(), c.end()); } }; class Text : public Node { public: const std::string text; Text(Manager &mgr, Handle parent, std::string text) : Node(mgr, parent), text(std::move(text)) { } /** * This just writes the text to the output. * */ void doSerialize(std::ostream &out, unsigned int tabdepth, bool pretty) override; }; } namespace RttiTypes { extern const RttiType XMLNode; extern const RttiType XMLElement; extern const RttiType XMLText; } } #endif