/* * XML Parser/Generator * * Copyright (C) 2001 Barnaby Gray . * * 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 2 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, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include "simapi.h" #include "xml.h" // ---------- XmlNode --------------------------- XmlNode::XmlNode(const string& t) : tag(t) { } XmlNode::~XmlNode() { } bool XmlNode::isLeaf() { return !isBranch(); } string XmlNode::getTag() { return tag; } string XmlNode::replace_all(const string& s, const string& r1, const string& r2) { string t(s.c_str()); int curr = 0, next; while ( (next = t.find( r1, curr )) != -1) { t.replace( next, r1.size(), r2 ); curr = next + r2.size(); } return t; } string XmlNode::quote(const string& a) { return replace_all( replace_all( replace_all(a, "&", "&"), "<", "<"), ">", ">"); } string XmlNode::unquote(const string& a) { return replace_all( replace_all( replace_all(a, "<", "<"), ">", ">"), "&", "&"); } XmlNode *XmlNode::parse(string::iterator& curr, string::iterator end) { skipWS(curr,end); if (curr == end || *curr != '<') return NULL; string tag = parseTag(curr,end); if (tag.empty() || tag[0] == '/') return NULL; skipWS(curr,end); if (curr == end) return NULL; if (*curr == '<') { XmlNode *p = NULL; while (curr != end) { string::iterator mark = curr; string nexttag = parseTag(curr,end); if (nexttag.empty()) { if (p != NULL) delete p; return NULL; } if (nexttag[0] == '/') { // should be the closing if (nexttag.size() == tag.size()+1 && nexttag.find(tag,1) == 1) { // is closing tag if (p == NULL) p = new XmlLeaf(unquote(tag),""); return p; } else { if (p != NULL) delete p; return NULL; } } else { if (p == NULL) p = new XmlBranch(unquote(tag)); // an opening tag curr = mark; XmlNode *c = parse(curr,end); if (c != NULL) ((XmlBranch*)p)->pushnode(c); } skipWS(curr,end); if(curr == end || *curr != '<') { if (p != NULL) delete p; } } return NULL; } // XmlLeaf string value; while (curr != end && *curr != '<') { value += *curr; curr++; } if(curr == end) return NULL; string nexttag = parseTag(curr,end); if (nexttag.empty() || nexttag[0] != '/') return NULL; if (nexttag.size() == tag.size()+1 && nexttag.find(tag,1) == 1) { return new XmlLeaf(unquote(tag),unquote(value)); } // error return NULL; } string XmlNode::parseTag(string::iterator& curr, string::iterator end) { string tag; if(curr == end || *curr != '<') return string(); curr++; while(curr != end && *curr != '>') { tag += *curr; curr++; } if (curr == end) return string(); curr++; return tag; } void XmlNode::skipWS(string::iterator& curr, string::iterator end) { while(curr != end && isspace(*curr)) curr++; } // ----------- XmlBranch ------------------------ XmlBranch::XmlBranch(const string& t) : XmlNode(t) { } XmlBranch::~XmlBranch() { list::iterator curr = children.begin(); while (curr != children.end()) { delete (*curr); curr++; } children.clear(); } bool XmlBranch::isBranch() { return true; } bool XmlBranch::exists(const string& tag) { list::iterator curr = children.begin(); while (curr != children.end()) { if ((*curr)->getTag() == tag) return true; curr++; } return false; } XmlNode *XmlBranch::getNode(const string& tag) { list::iterator curr = children.begin(); while (curr != children.end()) { if ((*curr)->getTag() == tag) return (*curr); curr++; } return NULL; } XmlBranch *XmlBranch::getBranch(const string& tag) { XmlNode *t = getNode(tag); if (t == NULL || !t->isBranch()) return NULL; return static_cast(t); } XmlLeaf *XmlBranch::getLeaf(const string& tag) { XmlNode *t = getNode(tag); if (t == NULL || !t->isLeaf()) return NULL; return static_cast(t); } void XmlBranch::pushnode(XmlNode *c) { children.push_back(c); } string XmlBranch::toString(int n) { string ret(n,'\t'); ret += "<" + quote(tag) + ">\n"; list::iterator curr = children.begin(); while (curr != children.end()) { ret += (*curr)->toString(n+1); curr++; } ret += string(n,'\t') + "\n"; return ret; } // ----------- XmlLeaf -------------------------- XmlLeaf::XmlLeaf(const string& t, const string& v) : XmlNode(t), value(v) { } XmlLeaf::~XmlLeaf() { } bool XmlLeaf::isBranch() { return false; } string XmlLeaf::getValue() { return value; } string XmlLeaf::toString(int n) { return string(n,'\t') + "<" + quote(tag) + ">" + quote(value) + "\n"; }