summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvisvgm/dvisvgm-1.9.2/src/XMLNode.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/dvisvgm/dvisvgm-1.9.2/src/XMLNode.cpp')
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-1.9.2/src/XMLNode.cpp254
1 files changed, 254 insertions, 0 deletions
diff --git a/Build/source/texk/dvisvgm/dvisvgm-1.9.2/src/XMLNode.cpp b/Build/source/texk/dvisvgm/dvisvgm-1.9.2/src/XMLNode.cpp
new file mode 100644
index 00000000000..4fd3b997391
--- /dev/null
+++ b/Build/source/texk/dvisvgm/dvisvgm-1.9.2/src/XMLNode.cpp
@@ -0,0 +1,254 @@
+/*************************************************************************
+** XMLNode.cpp **
+** **
+** This file is part of dvisvgm -- the DVI to SVG converter **
+** Copyright (C) 2005-2015 Martin Gieseking <martin.gieseking@uos.de> **
+** **
+** 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 <http://www.gnu.org/licenses/>. **
+*************************************************************************/
+
+#include <config.h>
+#include <map>
+#include <list>
+#include "macros.h"
+#include "XMLNode.h"
+#include "XMLString.h"
+
+using namespace std;
+
+
+XMLElementNode::XMLElementNode (const string &n) : _name(n) {
+}
+
+
+XMLElementNode::XMLElementNode (const XMLElementNode &node)
+ : _name(node._name), _attributes(node._attributes)
+{
+ FORALL(node._children, ChildList::const_iterator, it)
+ _children.push_back((*it)->clone());
+}
+
+
+XMLElementNode::~XMLElementNode () {
+ while (!_children.empty()) {
+ delete _children.back();
+ _children.pop_back();
+ }
+}
+
+
+void XMLElementNode::clear () {
+ _attributes.clear();
+ while (!_children.empty()) {
+ delete _children.back();
+ _children.pop_back();
+ }
+}
+
+
+void XMLElementNode::addAttribute (const string &name, const string &value) {
+ _attributes[name] = value;
+}
+
+
+void XMLElementNode::addAttribute (const string &name, double value) {
+ _attributes[name] = XMLString(value);
+}
+
+
+void XMLElementNode::append (XMLNode *child) {
+ if (!child)
+ return;
+ XMLTextNode *textNode1 = dynamic_cast<XMLTextNode*>(child);
+ if (!textNode1 || _children.empty())
+ _children.push_back(child);
+ else {
+ if (XMLTextNode *textNode2 = dynamic_cast<XMLTextNode*>(_children.back()))
+ textNode2->append(textNode1); // merge two consecutive text nodes
+ else
+ _children.push_back(child);
+ }
+}
+
+
+void XMLElementNode::append (const string &str) {
+ if (_children.empty() || !dynamic_cast<XMLTextNode*>(_children.back()))
+ _children.push_back(new XMLTextNode(str));
+ else
+ static_cast<XMLTextNode*>(_children.back())->append(str);
+}
+
+
+void XMLElementNode::prepend (XMLNode *child) {
+ if (!child)
+ return;
+ XMLTextNode *textNode1 = dynamic_cast<XMLTextNode*>(child);
+ if (!textNode1 || _children.empty())
+ _children.push_front(child);
+ else {
+ if (XMLTextNode *textNode2 = dynamic_cast<XMLTextNode*>(_children.front()))
+ textNode2->prepend(textNode1); // merge two consecutive text nodes
+ else
+ _children.push_front(child);
+ }
+}
+
+
+/** Inserts a new child node before a given child node already present. The latter
+ * will be the following sibling of the node to be inserted. If there's no such
+ * node present, nothing is inserted.
+ * @param[in] child node to be inserted
+ * @param[in] sibling following sibling of 'child'
+ * @return true on success */
+bool XMLElementNode::insertBefore (XMLNode *child, XMLNode *sibling) {
+ ChildList::iterator it = _children.begin();
+ while (it != _children.end() && *it != sibling)
+ ++it;
+ if (it == _children.end())
+ return false;
+ _children.insert(it, child);
+ return true;
+}
+
+
+/** Inserts a new child node after a given child node already present. The latter
+ * will be the preceding sibling of the node to be inserted. If there's no such
+ * node present, nothing is inserted.
+ * @param[in] child node to be inserted
+ * @param[in] sibling preceding sibling of 'child'
+ * @return true on success */
+bool XMLElementNode::insertAfter (XMLNode *child, XMLNode *sibling) {
+ ChildList::iterator it = _children.begin();
+ while (it != _children.end() && *it != sibling)
+ ++it;
+ if (it == _children.end())
+ return false;
+ _children.insert(++it, child);
+ return true;
+}
+
+
+/** Gets all descendant elements with a given name and given attribute.
+ * @param[in] name name of elements to find
+ * @param[in] attrName name of attribute to find
+ * @param[out] descendants all elements found
+ * @return true if at least one element was found */
+bool XMLElementNode::getDescendants (const char *name, const char *attrName, vector<XMLElementNode*> &descendants) const {
+ FORALL(_children, ChildList::const_iterator, it) {
+ if (XMLElementNode *elem = dynamic_cast<XMLElementNode*>(*it)) {
+ if ((!name || elem->getName() == name) && (!attrName || elem->hasAttribute(attrName)))
+ descendants.push_back(elem);
+ elem->getDescendants(name, attrName, descendants);
+ }
+ }
+ return !descendants.empty();
+}
+
+
+/** Returns the first descendant element that matches the given properties in depth first order.
+ * @param[in] name element name; if 0, all elements are taken into account
+ * @param[in] attrName if not 0, only elements with an attribute of this name are considered
+ * @param[in] attrValue if not 0, only elements with attribute attrName="attrValue" are considered
+ * @return pointer to the found element or 0 */
+XMLElementNode* XMLElementNode::getFirstDescendant (const char *name, const char *attrName, const char *attrValue) const {
+ FORALL(_children, ChildList::const_iterator, it) {
+ if (XMLElementNode *elem = dynamic_cast<XMLElementNode*>(*it)) {
+ if (!name || elem->getName() == name) {
+ const char *value;
+ if (!attrName || (((value = elem->getAttributeValue(attrName)) != 0) && (!attrValue || string(value) == attrValue)))
+ return elem;
+ }
+ if (XMLElementNode *descendant = elem->getFirstDescendant(name, attrName, attrValue))
+ return descendant;
+ }
+ }
+ return 0;
+}
+
+
+ostream& XMLElementNode::write (ostream &os) const {
+ os << '<' << _name;
+ FORALL(_attributes, AttribMap::const_iterator, i)
+ os << ' ' << i->first << "='" << i->second << '\'';
+ if (_children.empty())
+ os << "/>\n";
+ else {
+ os << '>';
+ if (dynamic_cast<XMLElementNode*>(_children.front()))
+ os << '\n';
+ FORALL(_children, ChildList::const_iterator, i)
+ (*i)->write(os);
+ os << "</" << _name << ">\n";
+ }
+ return os;
+}
+
+
+/** Returns true if this element has an attribute of given name. */
+bool XMLElementNode::hasAttribute (const string &name) const {
+ return _attributes.find(name) != _attributes.end();
+}
+
+
+/** Returns the value of an attribute.
+ * @param[in] name name of attribute
+ * @return attribute value or 0 if attribute doesn't exist */
+const char* XMLElementNode::getAttributeValue(const std::string& name) const {
+ AttribMap::const_iterator it = _attributes.find(name);
+ if (it != _attributes.end())
+ return it->second.c_str();
+ return 0;
+}
+
+
+//////////////////////
+
+void XMLTextNode::append (XMLNode *node) {
+ if (XMLTextNode *tn = dynamic_cast<XMLTextNode*>(node))
+ append(tn);
+ else
+ delete node;
+}
+
+
+void XMLTextNode::append (XMLTextNode *node) {
+ if (node)
+ _text += node->_text;
+ delete node;
+}
+
+
+void XMLTextNode::append (const string &str) {
+ _text += str;
+}
+
+
+void XMLTextNode::prepend (XMLNode *node) {
+ if (XMLTextNode *tn = dynamic_cast<XMLTextNode*>(node))
+ _text = tn->_text + _text;
+ else
+ delete node;
+}
+
+
+//////////////////////
+
+
+ostream& XMLCDataNode::write (ostream &os) const {
+ if (!_data.empty())
+ os << "<![CDATA[\n" << _data << "]]>\n";
+ return os;
+}
+
+