/** * @file xml.h * * Classes providing support for XML data files. These classes * implement only those aspects of XML required to read, write, and * manipulate CTML data files. */ /* $Author$ * $Revision$ * $Date$ */ // Copyright 2001 California Institute of Technology #ifndef CT_XML #define CT_XML #include #include #include using namespace std; #include "ctexceptions.h" #include "ct_defs.h" #include "stringUtils.h" #include #include "global.h" #define XML_INDENT 4 namespace Cantera { /** * Class XML_Reader is designed for internal use. */ class XML_Reader { public: XML_Reader(istream& input) : m_s(input), m_line(0) {} istream& m_s; int m_line; void getchr(char& ch); string strip(const string& aline); string inquotes(const string& aline); int findQuotedString(const string& aline, string &rstring); void parseTag(string line, string& name, map& attribs); string readTag(map& attribs); string readValue(); }; ////////////////////////// XML_Node ///////////////////////////////// class XML_Node { public: XML_Node(string nm = "--", XML_Node* p = 0, int n = 0); virtual ~XML_Node(); void addComment(string comment); XML_Node& addChild(XML_Node& node); XML_Node& addChild(string name); XML_Node& addChild(string name, string value); XML_Node& addChild(string name, double value, string fmt="%g"); void removeChild(XML_Node* node); void addValue(string val); void addValue(doublereal val, string fmt="%g"); void addAttribute(string attrib, string value); void addAttribute(string attrib, double value, string fmt="%g"); void writeHeader(ostream& s); string value() const { return m_value; } string value(string loc) const { return child(loc).value(); } doublereal fp_value() const { return atof(m_value.c_str()); } integer int_value() const { return atoi(m_value.c_str()); } string operator()() const { return m_value; } string operator()(string loc) const { return value(loc); } /** * The operator[] is overloaded to provide a lookup capability * on attributes for the current XML element. * * For example * xmlNode["id"] * will return the value of the attribute "id" for the current * XML element. It will return the blank string if there isn't * an attribute with that name. */ string operator[](string attr) const { return attrib(attr); } string attrib(string attr) const { map::const_iterator i = m_attribs.find(attr); if (i != m_attribs.end()) return i->second; else return ""; } map& attribs() { return m_attribs; } XML_Node* parent() const { return m_parent; } XML_Node* setParent(XML_Node* p) { m_parent = p; return p; } bool hasChild(string ch) const { return (m_childindex.find(ch) != m_childindex.end()); //return (m_childindex[ch] != 0); } bool hasAttrib(string a) const { return (m_attribs.find(a) != m_attribs.end()); //if (m_attribs[a] != "") return true; //else { // m_attribs.erase(a); // return false; //} } string name() const { return m_name; } string id() const { if (hasAttrib("id")) return attrib("id"); else return ""; } int number() const { return m_n; } XML_Node& child(int n) const { return *m_children[n]; } //const XML_Node& child(int n) const { return *m_children[n]; } vector& children() { return m_children; } const vector& children() const { return m_children; } int nChildren() const { return m_nchildren; } void build(istream& f); XML_Node* findID(const string& id, int depth=100); XML_Node* findByAttr(const string& attr, const string& val); XML_Node* findByName(const string& nm); void getChildren(string name, vector& children) const; XML_Node& child(string loc) const; void write(ostream& s, int level = 0); //const XML_Node* getRef() const; XML_Node& root() const { return *m_root; } void setRoot(XML_Node& root) { m_root = &root; } void copyUnion(XML_Node *node_dest); void copy(XML_Node *node_dest); private: void write_int(ostream& s, int level = 0); protected: string m_name; string m_value; int m_level; map m_childindex; map m_attribs; XML_Node* m_parent; XML_Node* m_root; vector m_children; int m_nchildren; int m_n; bool m_iscomment; }; ////////////////////// XML_Writer ////////////////////////// class XML_Writer { public: XML_Writer(ostream& output) : m_s(output), _indent(" "), _level(0) {} virtual ~XML_Writer() {} ostream& m_s; string _indent; int _level; ostream& output() { return m_s; } inline string XML_filter(string name) { int ns = name.size(); string nm(name); for (int m = 0; m < ns; m++) if (name[m] == ' ' || name[m] == '(' || name[m] == ')') nm[m] = '_'; return nm; } /** * XML_comment() * * Add a comment element to the current XML output file * Comment elements start with * Comments are indented according to the current lvl, * _level * * input * --------- * s : Output stream containing the XML file * comment : Reference to a string containing the comment */ inline void XML_comment(ostream& s, const string& comment) { for (int n = 0; n < _level; n++) s << _indent; s << "" << endl; } inline void XML_open(ostream& s, const string& tag, const string p = "") { for (int n = 0; n < _level; n++) s << _indent; _level++; s << "<" << XML_filter(tag) << p << ">" << endl; } inline void XML_close(ostream& s, const string& tag) { _level--; for (int n = 0; n < _level; n++) s << _indent; s << "" << endl; } template void XML_item(ostream& s, const string& tag, T value) { for (int n = 0; n < _level; n++) s << _indent; s << "<" << XML_filter(tag) << ">" << value << "" << endl; } template void XML_writeVector(ostream& s, const string& indent, const string& name, int vsize, iter v) { int ni; for (ni = 0; ni < _level; ni++) s << _indent; s << "<" << XML_filter(name) << "> "; int n = vsize; int n5 = n/5; int i, j, k = 0; for (j = 0; j < n5; j++) { for (i = 0; i < 5; i++) { s << v[k] << (k < n - 1 ? ", " : ""); k++; } if (j < n5-1) { s << endl; for (ni = 0; ni < _level; ni++) s << _indent; } } for (i = k; i < n; i++) { s << v[k] << (k < n - 1 ? ", " : ""); k++; } s << "" << endl; } }; //XML_Node* find_XML(string src, XML_Node* root=0, // string id="", string loc="", string name=""); XML_Node * const findXMLPhase(XML_Node* root, string id); } #endif