From 33f57678330a5c62e0673b3a8554854e2b3d3b18 Mon Sep 17 00:00:00 2001 From: Harry Moffat Date: Fri, 31 Oct 2008 16:46:49 +0000 Subject: [PATCH] More documentation of XML_Node --- Cantera/src/base/xml.cpp | 1122 ++++++++++++++++++++------------------ Cantera/src/base/xml.h | 52 +- 2 files changed, 638 insertions(+), 536 deletions(-) diff --git a/Cantera/src/base/xml.cpp b/Cantera/src/base/xml.cpp index 0f3bc9e6a..c291dea4d 100755 --- a/Cantera/src/base/xml.cpp +++ b/Cantera/src/base/xml.cpp @@ -1,3 +1,16 @@ +/** + * @file xml.cpp + * 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 // simple xml functions @@ -25,66 +38,66 @@ using namespace std; namespace Cantera { - ////////////////////// exceptions //////////////////////////// + ////////////////////// exceptions //////////////////////////// - class XML_Error : public CanteraError { - public: - XML_Error(int line=0) : m_line(line) { - m_msg = "Error in XML file"; - if (line > 0) { - m_msg += " at line " + int2str(line+1); - } - m_msg += ".\n"; - //setError("XML_Error",m_msg); - } - virtual ~XML_Error() {} - protected: - int m_line; - string m_msg; - }; + class XML_Error : public CanteraError { + public: + XML_Error(int line=0) : m_line(line) { + m_msg = "Error in XML file"; + if (line > 0) { + m_msg += " at line " + int2str(line+1); + } + m_msg += ".\n"; + //setError("XML_Error",m_msg); + } + virtual ~XML_Error() {} + protected: + int m_line; + string m_msg; + }; - class XML_TagMismatch : public XML_Error { - public: - XML_TagMismatch(string opentag, string closetag, - int line=0) : XML_Error(line) { - m_msg += "<" + opentag + "> paired with .\n"; - setError("XML_TagMismatch",m_msg); - } - virtual ~XML_TagMismatch() {} - }; + class XML_TagMismatch : public XML_Error { + public: + XML_TagMismatch(string opentag, string closetag, + int line=0) : XML_Error(line) { + m_msg += "<" + opentag + "> paired with .\n"; + setError("XML_TagMismatch",m_msg); + } + virtual ~XML_TagMismatch() {} + }; - class XML_NoChild : public XML_Error { - public: - XML_NoChild(const XML_Node* p, string parent, - string child, int line=0) : XML_Error(line) { - m_msg += " The XML Node \"" + parent + - "\", does not contain a required\n" + - " XML child node named \"" - + child + "\".\n"; + class XML_NoChild : public XML_Error { + public: + XML_NoChild(const XML_Node* p, string parent, + string child, int line=0) : XML_Error(line) { + m_msg += " The XML Node \"" + parent + + "\", does not contain a required\n" + + " XML child node named \"" + + child + "\".\n"; #ifdef HAS_SSTREAM - ostringstream ss(ostringstream::out); - p->write(ss,1); - m_msg += ss.str() + "\n"; + ostringstream ss(ostringstream::out); + p->write(ss,1); + m_msg += ss.str() + "\n"; #endif - setError("XML_NoChild",m_msg); - } - virtual ~XML_NoChild() {} - }; + setError("XML_NoChild",m_msg); + } + virtual ~XML_NoChild() {} + }; - class XML_IllegalUnits : public XML_Error { - public: - XML_IllegalUnits(string name, string units, int line=0) : XML_Error(line) { - m_msg += "Illegal units (" + units + - ") specified for node " + name + ".\n"; - setError("XML_IllegalUnits",m_msg); - } - virtual ~XML_IllegalUnits() {} - }; + class XML_IllegalUnits : public XML_Error { + public: + XML_IllegalUnits(string name, string units, int line=0) : XML_Error(line) { + m_msg += "Illegal units (" + units + + ") specified for node " + name + ".\n"; + setError("XML_IllegalUnits",m_msg); + } + virtual ~XML_IllegalUnits() {} + }; - //////////////////// XML_Reader methods /////////////////////// + //////////////////// XML_Reader methods /////////////////////// XML_Reader::XML_Reader(std::istream& input) : @@ -311,27 +324,48 @@ namespace Cantera { ////////////////////////// XML_Node ///////////////////////////////// + // Default constructor for XML_Node, representing a tree structure + /* + * Constructor for an XML_Node, which is a node in a tree-like structure + * representing an XML file. + * + * @param nm Name of the node. + * The default name of the node is "--" + * + * @param p pointer to the root for this node in the tree. + * The default is 0 indicating this is the top of the tree. + */ + XML_Node::XML_Node(const string nm, XML_Node * const p) + : m_name(nm), + m_value(""), + m_parent(p), + m_locked(false), + m_nchildren(0), + m_iscomment(false) + { + if (!p) m_root = this; + else m_root = &p->root(); + } - XML_Node::XML_Node(string nm, XML_Node* p) - : m_name(nm), m_value(""), m_parent(p), - m_locked(false), m_nchildren(0), - m_iscomment(false) { - if (!p) m_root = this; - else m_root = &p->root(); - } - + // Copy constructor + /* + * @param right Object to be copied + */ XML_Node::XML_Node(const XML_Node &right) : - m_name(""), - m_value(""), - m_parent(0), - m_locked(false), - m_nchildren(0), - m_iscomment(false) + m_name(""), + m_value(""), + m_parent(0), + m_locked(false), + m_nchildren(0), + m_iscomment(false) { right.copy(this); } - + // Assignment operator for XML trees + /* + * @param right XML tree to copy + */ XML_Node & XML_Node::operator=(const XML_Node &right) { if (&right != this) { @@ -350,8 +384,7 @@ namespace Cantera { return *this; } - - + // Destructor for the object XML_Node::~XML_Node() { if (m_locked) throw CanteraError("XML_Node::~XML_Node", @@ -367,39 +400,64 @@ namespace Cantera { } } - void XML_Node::addComment(string comment) { - addChild("comment",comment); + // Add a child node to the current node containing a comment + /* + * Child node will have the name, "comment". + * + * @param comment Content of the comment + */ + void XML_Node::addComment(const std::string comment) { + addChild("comment", comment); } - XML_Node& XML_Node::addChild(XML_Node& node) { - m_children.push_back(&node); - m_nchildren = static_cast(m_children.size()); - m_childindex[node.name()] = m_children.back(); - node.setRoot(root()); - return *m_children.back(); - } + // Add a child node to the current node + /* + * This will add an XML_Node as a child to the current node. + * Note, this actually adds the node. Therefore, node is changed. + * There is no copy made of the child node. + * + * @param node Reference to a child XML_Node object + * + * @return returns a reference to the added node + */ + XML_Node& XML_Node::addChild(XML_Node& node) { + m_children.push_back(&node); + m_nchildren = static_cast(m_children.size()); + m_childindex[node.name()] = m_children.back(); + node.setRoot(root()); + return *m_children.back(); + } - XML_Node& XML_Node::addChild(string name) { - XML_Node *xxx = new XML_Node(name, this); - m_children.push_back(xxx); - m_nchildren = static_cast(m_children.size()); - m_childindex[name] = m_children.back(); - m_children.back()->setParent(this); - return *m_children.back(); - } + // Add a child node to the current node with a specified name + /* + * This will add an XML_Node as a child to the current node. + * The node will be blank except for the specified name. + * + * @param sname Name of the new child + * + * @return Returns a reference to the added node + */ + XML_Node& XML_Node::addChild(const std::string sname) { + XML_Node *xxx = new XML_Node(sname, this); + m_children.push_back(xxx); + m_nchildren = static_cast(m_children.size()); + m_childindex[sname] = m_children.back(); + m_children.back()->setParent(this); + return *m_children.back(); + } - void XML_Node::removeChild(XML_Node* node) { - vector::iterator i; - i = find(m_children.begin(), m_children.end(), node); - m_children.erase(i); - m_nchildren = static_cast(m_children.size()); - m_childindex.erase(node->name()); - } + void XML_Node::removeChild(XML_Node* node) { + vector::iterator i; + i = find(m_children.begin(), m_children.end(), node); + m_children.erase(i); + m_nchildren = static_cast(m_children.size()); + m_childindex.erase(node->name()); + } - std::string XML_Node::id() const { - if (hasAttrib("id")) return attrib("id"); - return std::string(""); - } + std::string XML_Node::id() const { + if (hasAttrib("id")) return attrib("id"); + return std::string(""); + } // The operator[] is overloaded to provide a lookup capability @@ -440,240 +498,240 @@ namespace Cantera { return ""; } - /** - * This routine carries out a search for an XML node based - * on both the xml element name and the attribute ID. - * If exact matches are found for both fields, the pointer - * to the matching XML Node is returned. - * - * The ID attribute may be defaulted by setting it to "". - * In this case the pointer to the first xml element matching the name - * is returned. - * - * This algorithm does a lateral search of first generation children - * first before diving deeper into each tree branch. - */ - XML_Node* XML_Node:: - findNameID(const string &nameTarget, const string &idTarget) const { - XML_Node *scResult = 0; - XML_Node *sc; - string idattrib = id(); - int n; - if (name() == nameTarget) { - if (idTarget == "" || idTarget == idattrib) { - return const_cast(this); + /** + * This routine carries out a search for an XML node based + * on both the xml element name and the attribute ID. + * If exact matches are found for both fields, the pointer + * to the matching XML Node is returned. + * + * The ID attribute may be defaulted by setting it to "". + * In this case the pointer to the first xml element matching the name + * is returned. + * + * This algorithm does a lateral search of first generation children + * first before diving deeper into each tree branch. + */ + XML_Node* XML_Node:: + findNameID(const string &nameTarget, const string &idTarget) const { + XML_Node *scResult = 0; + XML_Node *sc; + string idattrib = id(); + int n; + if (name() == nameTarget) { + if (idTarget == "" || idTarget == idattrib) { + return const_cast(this); + } + } + for (n = 0; n < m_nchildren; n++) { + sc = m_children[n]; + if (sc->name() == nameTarget) { + if (idTarget == "") return sc; + idattrib = sc->id(); + if (idTarget == idattrib) return sc; + } + } + for (n = 0; n < m_nchildren; n++) { + sc = m_children[n]; + scResult = sc->findNameID(nameTarget, idTarget); + if (scResult) return scResult; + } + return scResult; + } + + + XML_Node* XML_Node::findID(const string& id, int depth) const { + if (hasAttrib("id")) { + if (attrib("id") == id) { + return const_cast(this); + } + } + if (depth > 0) { + XML_Node* r = 0; + int n = nChildren(); + for (int i = 0; i < n; i++) { + r = m_children[i]->findID(id, depth-1); + if (r != 0) return r; + } + } + return 0; + } + + XML_Node* XML_Node::findByAttr(const string& attr, + const string& val) { + if (hasAttrib(attr)) { + if (attrib(attr) == val) { + return this; + } + } + XML_Node* r = 0; + int n = nChildren(); + for (int i = 0; i < n; i++) { + r = m_children[i]->findByAttr(attr, val); + if (r != 0) return r; + } + return 0; + } + + XML_Node* XML_Node::findByName(const string& nm) { + if (name() == nm) { + return this; + } + XML_Node* r = 0; + int n = nChildren(); + for (int i = 0; i < n; i++) { + r = m_children[i]->findByName(nm); + if (r != 0) return r; + } + return 0; + } + + const XML_Node* XML_Node::findByName(const string& nm) const { + if (name() == nm) { + return this; + } + const XML_Node* r = 0; + int n = nChildren(); + for (int i = 0; i < n; i++) { + r = m_children[i]->findByName(nm); + if (r != 0) return r; + } + return 0; + } + + /** + * addChild(string name, string value): + * + * Add a child node to the current xml node, and at the + * same time add a value to the child + * + * Resulting XML string: + * value + * + * Return + * ------- + * Returns a reference to the created child XML_Node object + */ + XML_Node& XML_Node::addChild(string name, string value) { + XML_Node& c = addChild(name); + c.addValue(value); + return c; + } + + XML_Node& XML_Node::addChild(string name, double value, string fmt) { + XML_Node& c = addChild(name); + c.addValue(value,fmt); + return c; + } + + void XML_Node::addValue(string val) { + m_value = val; + if (m_name == "comment") m_iscomment = true; + } + void XML_Node::addValue(doublereal val, string fmt) { + char buf[30]; + sprintf(buf,fmt.c_str(),val); + m_value = stripws(buf); + } + + void XML_Node::addAttribute(string attrib, string value) { + m_attribs[attrib] = value; + } + void XML_Node::addAttribute(string attrib, double value, string fmt) { + m_attribs[attrib] = fp2str(value, fmt); + } + + void XML_Node::writeHeader(ostream& s) { + s << "" << endl; + } + + void XML_Node::build(istream& f) { + XML_Reader r(f); + string nm, nm2, val; + XML_Node* node = this; + map attribs; + while (!f.eof()) { + attribs.clear(); + nm = r.readTag(attribs); + + if (nm == "EOF") break; + if (nm == "--" && m_name == "--" && m_root == this) { + continue; + } + int lnum = r.m_line; + if (nm[nm.size() - 1] == '/') { + nm2 = nm.substr(0,nm.size()-1); + node = &node->addChild(nm2); + node->addValue(""); + node->attribs() = attribs; + node->setLineNumber(lnum); + node = node->parent(); + } + else if (nm[0] != '/') { + if (nm[0] != '!' && nm[0] != '-' && nm[0] != '?') { + node = &node->addChild(nm); + val = r.readValue(); + node->addValue(val); + node->attribs() = attribs; + node->setLineNumber(lnum); + } + else if (nm.substr(0,2) == "--") { + if (nm.substr(nm.size()-2,2) == "--") { + node->addComment(nm.substr(2,nm.size()-4)); } } - for (n = 0; n < m_nchildren; n++) { - sc = m_children[n]; - if (sc->name() == nameTarget) { - if (idTarget == "") return sc; - idattrib = sc->id(); - if (idTarget == idattrib) return sc; - } - } - for (n = 0; n < m_nchildren; n++) { - sc = m_children[n]; - scResult = sc->findNameID(nameTarget, idTarget); - if (scResult) return scResult; - } - return scResult; + } + else { + if (node->name() != nm.substr(1,nm.size()-1)) + throw XML_TagMismatch(node->name(), + nm.substr(1,nm.size()-1), lnum); + node = node->parent(); + } } - + } - XML_Node* XML_Node::findID(const string& id, int depth) const { - if (hasAttrib("id")) { - if (attrib("id") == id) { - return const_cast(this); - } - } - if (depth > 0) { - XML_Node* r = 0; - int n = nChildren(); - for (int i = 0; i < n; i++) { - r = m_children[i]->findID(id, depth-1); - if (r != 0) return r; - } - } - return 0; + void XML_Node::copyUnion(XML_Node *node_dest) const { + XML_Node *sc, *dc; + int ndc, idc; + node_dest->addValue(m_value); + if (m_name == "") return; + map::const_iterator b = m_attribs.begin(); + for (; b != m_attribs.end(); ++b) { + if (! node_dest->hasAttrib(b->first)) { + node_dest->addAttribute(b->first, b->second); + } } - - XML_Node* XML_Node::findByAttr(const string& attr, - const string& val) { - if (hasAttrib(attr)) { - if (attrib(attr) == val) { - return this; - } - } - XML_Node* r = 0; - int n = nChildren(); - for (int i = 0; i < n; i++) { - r = m_children[i]->findByAttr(attr, val); - if (r != 0) return r; - } - return 0; - } - - XML_Node* XML_Node::findByName(const string& nm) { - if (name() == nm) { - return this; - } - XML_Node* r = 0; - int n = nChildren(); - for (int i = 0; i < n; i++) { - r = m_children[i]->findByName(nm); - if (r != 0) return r; - } - return 0; - } - - const XML_Node* XML_Node::findByName(const string& nm) const { - if (name() == nm) { - return this; - } - const XML_Node* r = 0; - int n = nChildren(); - for (int i = 0; i < n; i++) { - r = m_children[i]->findByName(nm); - if (r != 0) return r; - } - return 0; - } - - /** - * addChild(string name, string value): - * - * Add a child node to the current xml node, and at the - * same time add a value to the child - * - * Resulting XML string: - * value - * - * Return - * ------- - * Returns a reference to the created child XML_Node object - */ - XML_Node& XML_Node::addChild(string name, string value) { - XML_Node& c = addChild(name); - c.addValue(value); - return c; - } - - XML_Node& XML_Node::addChild(string name, double value, string fmt) { - XML_Node& c = addChild(name); - c.addValue(value,fmt); - return c; - } - - void XML_Node::addValue(string val) { - m_value = val; - if (m_name == "comment") m_iscomment = true; - } - void XML_Node::addValue(doublereal val, string fmt) { - char buf[30]; - sprintf(buf,fmt.c_str(),val); - m_value = stripws(buf); - } - - void XML_Node::addAttribute(string attrib, string value) { - m_attribs[attrib] = value; - } - void XML_Node::addAttribute(string attrib, double value, string fmt) { - m_attribs[attrib] = fp2str(value, fmt); - } - - void XML_Node::writeHeader(ostream& s) { - s << "" << endl; - } - - void XML_Node::build(istream& f) { - XML_Reader r(f); - string nm, nm2, val; - XML_Node* node = this; - map attribs; - while (!f.eof()) { - attribs.clear(); - nm = r.readTag(attribs); - - if (nm == "EOF") break; - if (nm == "--" && m_name == "--" && m_root == this) { - continue; + const vector &vsc = node_dest->children(); + for (int n = 0; n < m_nchildren; n++) { + sc = m_children[n]; + ndc = node_dest->nChildren(); + dc = 0; + if (! sc->m_iscomment) { + for (idc = 0; idc < ndc; idc++) { + XML_Node *dcc = vsc[idc]; + if (dcc->name() == sc->name()) { + if (sc->hasAttrib("id")) { + if (sc->attrib("id") != dcc->attrib("id")) break; } - int lnum = r.m_line; - if (nm[nm.size() - 1] == '/') { - nm2 = nm.substr(0,nm.size()-1); - node = &node->addChild(nm2); - node->addValue(""); - node->attribs() = attribs; - node->setLineNumber(lnum); - node = node->parent(); - } - else if (nm[0] != '/') { - if (nm[0] != '!' && nm[0] != '-' && nm[0] != '?') { - node = &node->addChild(nm); - val = r.readValue(); - node->addValue(val); - node->attribs() = attribs; - node->setLineNumber(lnum); - } - else if (nm.substr(0,2) == "--") { - if (nm.substr(nm.size()-2,2) == "--") { - node->addComment(nm.substr(2,nm.size()-4)); - } - } - } - else { - if (node->name() != nm.substr(1,nm.size()-1)) - throw XML_TagMismatch(node->name(), - nm.substr(1,nm.size()-1), lnum); - node = node->parent(); - } - } - } - - void XML_Node::copyUnion(XML_Node *node_dest) const { - XML_Node *sc, *dc; - int ndc, idc; - node_dest->addValue(m_value); - if (m_name == "") return; - map::const_iterator b = m_attribs.begin(); - for (; b != m_attribs.end(); ++b) { - if (! node_dest->hasAttrib(b->first)) { - node_dest->addAttribute(b->first, b->second); - } - } - const vector &vsc = node_dest->children(); - for (int n = 0; n < m_nchildren; n++) { - sc = m_children[n]; - ndc = node_dest->nChildren(); - dc = 0; - if (! sc->m_iscomment) { - for (idc = 0; idc < ndc; idc++) { - XML_Node *dcc = vsc[idc]; - if (dcc->name() == sc->name()) { - if (sc->hasAttrib("id")) { - if (sc->attrib("id") != dcc->attrib("id")) break; - } - if (sc->hasAttrib("name")) { - if (sc->attrib("name") != dcc->attrib("name")) break; - } - if (sc->hasAttrib("model")) { - if (sc->attrib("model") != dcc->attrib("model")) break; - } - if (sc->hasAttrib("title")) { - if (sc->attrib("title") != dcc->attrib("title")) break; - } - dc = vsc[idc]; - } + if (sc->hasAttrib("name")) { + if (sc->attrib("name") != dcc->attrib("name")) break; } + if (sc->hasAttrib("model")) { + if (sc->attrib("model") != dcc->attrib("model")) break; + } + if (sc->hasAttrib("title")) { + if (sc->attrib("title") != dcc->attrib("title")) break; + } + dc = vsc[idc]; } - if (!dc) { - (void) node_dest->addChild(sc->name()); - dc = vsc[ndc]; - } - sc->copyUnion(dc); } + } + if (!dc) { + (void) node_dest->addChild(sc->name()); + dc = vsc[ndc]; + } + sc->copyUnion(dc); } + } void XML_Node::copy(XML_Node *node_dest) const { XML_Node *sc, *dc; @@ -695,239 +753,239 @@ namespace Cantera { } } - void XML_Node::getChildren(string nm, - vector& children) const { - int i, n = nChildren(); - for (i = 0; i < n; i++) { - if (child(i).name() == nm) { - children.push_back(&child(i)); - } - } + void XML_Node::getChildren(string nm, + vector& children) const { + int i, n = nChildren(); + for (i = 0; i < n; i++) { + if (child(i).name() == nm) { + children.push_back(&child(i)); + } } + } - XML_Node& XML_Node::child(string loc) const { - string::size_type iloc; - string cname; - map::const_iterator i; + XML_Node& XML_Node::child(string loc) const { + string::size_type iloc; + string cname; + map::const_iterator i; - while (1) { - iloc = loc.find('/'); - if (iloc != string::npos) { - cname = loc.substr(0,iloc); - loc = loc.substr(iloc+1, loc.size()); - i = m_childindex.find(cname); - //XML_Node* chld = m_childindex[cname]; - if (i != m_childindex.end()) return i->second->child(loc); - else { - throw XML_NoChild(this, m_name, cname, lineNumber()); - } - } - else { - i = m_childindex.find(loc); - if (i != m_childindex.end()) return *(i->second); - //XML_Node* chld = m_childindex[loc]; - //if (chld) return *chld; - else { - throw XML_NoChild(this, m_name, loc, lineNumber()); - } - } - } + while (1) { + iloc = loc.find('/'); + if (iloc != string::npos) { + cname = loc.substr(0,iloc); + loc = loc.substr(iloc+1, loc.size()); + i = m_childindex.find(cname); + //XML_Node* chld = m_childindex[cname]; + if (i != m_childindex.end()) return i->second->child(loc); + else { + throw XML_NoChild(this, m_name, cname, lineNumber()); + } + } + else { + i = m_childindex.find(loc); + if (i != m_childindex.end()) return *(i->second); + //XML_Node* chld = m_childindex[loc]; + //if (chld) return *chld; + else { + throw XML_NoChild(this, m_name, loc, lineNumber()); + } + } } + } - /** - * Write an XML subtree to an output stream. This is the - * main recursive routine. It doesn't put a final endl - * on. This is fixed up in the public method. - */ - void XML_Node::write_int(ostream& s, int level) const { + /** + * Write an XML subtree to an output stream. This is the + * main recursive routine. It doesn't put a final endl + * on. This is fixed up in the public method. + */ + void XML_Node::write_int(ostream& s, int level) const { - if (m_name == "") return; + if (m_name == "") return; - string indent(level, ' '); - if (m_iscomment) { - /* - * In the comment section, we test to see if there - * already is a space beginning and ending the comment. - * If there already is one, we don't add another one. - */ - s << endl << indent << ""; - return; - } + string indent(level, ' '); + if (m_iscomment) { + /* + * In the comment section, we test to see if there + * already is a space beginning and ending the comment. + * If there already is one, we don't add another one. + */ + s << endl << indent << ""; + return; + } - s << indent << "<" << m_name; - map::const_iterator b = m_attribs.begin(); - for (; b != m_attribs.end(); ++b) { - s << " " << b->first << "=\"" << b->second << "\""; - } - if (m_value == "" && m_nchildren == 0) { - s << "/>"; - } - else { - s << ">"; + s << indent << "<" << m_name; + map::const_iterator b = m_attribs.begin(); + for (; b != m_attribs.end(); ++b) { + s << " " << b->first << "=\"" << b->second << "\""; + } + if (m_value == "" && m_nchildren == 0) { + s << "/>"; + } + else { + s << ">"; - if (m_value != "") { - string vv = m_value; - string::size_type ieol = vv.find('\n'); - if (ieol != string::npos) { - while (1 > 0) { - ieol = vv.find('\n'); - if (ieol != string::npos) { - int jf = ieol - 1; - for (int j = 0; j < (int) ieol; j++) { - if (! isspace(vv[j])) { - jf = j; - break; - } - } - s << endl << indent << " " << vv.substr(jf,ieol-jf); - vv = vv.substr(ieol+1); - } - else { - int lll = static_cast(vv.size()) - 1; - if (lll >= 0) { - int jf = lll; - for (int j = 0; j < lll; j++) { - if (! isspace(vv[j])) { - jf = j; - break; - } - } - if (jf < lll) { - s << endl << indent << " " << vv.substr(jf); - } - } - break; - } - } - s << endl << indent; - } - else { - bool doSpace = true; - bool doNewLine = false; - int ll = static_cast(m_value.size()) - 1; - if (ll > 15) { - doNewLine = true; - } - if (m_name == "floatArray") { - doNewLine = true; - } - if (doNewLine) doSpace = false; - - if (doNewLine) { - s << endl << indent << " "; - } - /* - * Put spaces around a raw value field for readability - */ - if (doSpace && (! isspace(m_value[0]))) { - s << " "; - } - /* - * Write out the value - */ - s << m_value; - - if (doSpace && (! isspace(m_value[ll]))) { - s << " "; - } - if (doNewLine) { - s << endl << indent; + if (m_value != "") { + string vv = m_value; + string::size_type ieol = vv.find('\n'); + if (ieol != string::npos) { + while (1 > 0) { + ieol = vv.find('\n'); + if (ieol != string::npos) { + int jf = ieol - 1; + for (int j = 0; j < (int) ieol; j++) { + if (! isspace(vv[j])) { + jf = j; + break; + } + } + s << endl << indent << " " << vv.substr(jf,ieol-jf); + vv = vv.substr(ieol+1); + } + else { + int lll = static_cast(vv.size()) - 1; + if (lll >= 0) { + int jf = lll; + for (int j = 0; j < lll; j++) { + if (! isspace(vv[j])) { + jf = j; + break; } } - } - int i; - for (i = 0; i < m_nchildren; i++) { - s << endl; - m_children[i]->write_int(s,level + 2); - } - if (m_nchildren > 0) s << endl << indent; - s << ""; - } - } - - /** - * Write an XML subtree to an output stream. This is a - * wrapper around the static routine write_int(). All this - * does is add an endl on to the output stream. write_int() is - * fine, but the last endl wasn't being written. - * It also checks for the special name "--". If found and we - * are at the root of the xml tree, then the block - * is skipped and the children are processed. "--" is used - * to denote the top of the tree. - */ - void XML_Node::write(ostream& s, int level) const { - if (m_name == "--" && m_root == this) { - for (int i = 0; i < m_nchildren; i++) { - m_children[i]->write_int(s,level); - s << endl; - } - } else { - write_int(s, level); - s << endl; + if (jf < lll) { + s << endl << indent << " " << vv.substr(jf); + } + } + break; + } + } + s << endl << indent; } + else { + bool doSpace = true; + bool doNewLine = false; + int ll = static_cast(m_value.size()) - 1; + if (ll > 15) { + doNewLine = true; + } + if (m_name == "floatArray") { + doNewLine = true; + } + if (doNewLine) doSpace = false; + + if (doNewLine) { + s << endl << indent << " "; + } + /* + * Put spaces around a raw value field for readability + */ + if (doSpace && (! isspace(m_value[0]))) { + s << " "; + } + /* + * Write out the value + */ + s << m_value; + + if (doSpace && (! isspace(m_value[ll]))) { + s << " "; + } + if (doNewLine) { + s << endl << indent; + } + } + } + int i; + for (i = 0; i < m_nchildren; i++) { + s << endl; + m_children[i]->write_int(s,level + 2); + } + if (m_nchildren > 0) s << endl << indent; + s << ""; } + } - /** - * _require() - * Require that the current xml node have an attribute named - * by the first argument, a, and that this attribute have the - * the string value listed in the second argument, v. - * If not, throw a CanteraError exception. - */ - void XML_Node::_require(string a, string v) const { - if (hasAttrib(a)) { - if (attrib(a) == v) return; - } - string msg="XML_Node "+name()+" is required to have the value " - "\""+v+"\", but instead is \""+attrib(a); - throw CanteraError("XML_Node::require",msg); + /** + * Write an XML subtree to an output stream. This is a + * wrapper around the static routine write_int(). All this + * does is add an endl on to the output stream. write_int() is + * fine, but the last endl wasn't being written. + * It also checks for the special name "--". If found and we + * are at the root of the xml tree, then the block + * is skipped and the children are processed. "--" is used + * to denote the top of the tree. + */ + void XML_Node::write(ostream& s, int level) const { + if (m_name == "--" && m_root == this) { + for (int i = 0; i < m_nchildren; i++) { + m_children[i]->write_int(s,level); + s << endl; + } + } else { + write_int(s, level); + s << endl; } + } + + /** + * _require() + * Require that the current xml node have an attribute named + * by the first argument, a, and that this attribute have the + * the string value listed in the second argument, v. + * If not, throw a CanteraError exception. + */ + void XML_Node::_require(string a, string v) const { + if (hasAttrib(a)) { + if (attrib(a) == v) return; + } + string msg="XML_Node "+name()+" is required to have the value " + "\""+v+"\", but instead is \""+attrib(a); + throw CanteraError("XML_Node::require",msg); + } - XML_Node * findXMLPhase(XML_Node *root, - const string &idtarget) { - XML_Node *scResult = 0; - XML_Node *sc; - if (!root) return 0; - string idattrib; - string rname = root->name(); - if (rname == "phase") { - if (idtarget == "") return root; - idattrib = root->id(); - if (idtarget == idattrib) return root; - else return 0; - } - - const vector &vsc = root->children(); - int n; - for (n = 0; n < root->nChildren(); n++) { - sc = vsc[n]; - if (sc->name() == "phase") { - if (idtarget == "") return sc; - idattrib = sc->id(); - if (idtarget == idattrib) return sc; - } - } - for (n = 0; n < root->nChildren(); n++) { - sc = vsc[n]; - if (sc->name() != "phase") { - scResult = findXMLPhase(sc, idtarget); - if (scResult) return scResult; - } - } - return scResult; + XML_Node * findXMLPhase(XML_Node *root, + const string &idtarget) { + XML_Node *scResult = 0; + XML_Node *sc; + if (!root) return 0; + string idattrib; + string rname = root->name(); + if (rname == "phase") { + if (idtarget == "") return root; + idattrib = root->id(); + if (idtarget == idattrib) return root; + else return 0; } + const vector &vsc = root->children(); + int n; + for (n = 0; n < root->nChildren(); n++) { + sc = vsc[n]; + if (sc->name() == "phase") { + if (idtarget == "") return sc; + idattrib = sc->id(); + if (idtarget == idattrib) return sc; + } + } + for (n = 0; n < root->nChildren(); n++) { + sc = vsc[n]; + if (sc->name() != "phase") { + scResult = findXMLPhase(sc, idtarget); + if (scResult) return scResult; + } + } + return scResult; + } + } diff --git a/Cantera/src/base/xml.h b/Cantera/src/base/xml.h index 9c9d191c2..461a28f83 100755 --- a/Cantera/src/base/xml.h +++ b/Cantera/src/base/xml.h @@ -104,8 +104,23 @@ namespace Cantera { class XML_Node { public: - XML_Node(std::string nm = "--", XML_Node* p = 0); + //! Default constructor for XML_Node, representing a tree structure + /*! + * Constructor for an XML_Node, which is a node in a tree-like structure + * representing an XML file. + * + * @param nm Name of the node. + * The default name of the node is "--" + * + * @param p pointer to the root for this node in the tree. + * The default is 0 indicating this is the top of the tree. + */ + XML_Node(const std::string nm = "--", XML_Node * const p = 0); + //! Copy constructor + /*! + * @param right Object to be copied + */ XML_Node(const XML_Node &right); //! Assignment operator for XML trees @@ -114,11 +129,40 @@ namespace Cantera { */ XML_Node& operator=(const XML_Node &right); - + //! Destructor for the object virtual ~XML_Node(); - void addComment(std::string comment); + + //! Add a child node to the current node containing a comment + /*! + * Child node will have the name, comment. + * + * @param comment Content of the comment + */ + void addComment(const std::string comment); + + //! Add a child node to the current node + /*! + * This will add an XML_Node as a child to the current node. + * Note, this actually adds the node. Therefore, node is changed. + * There is no copy made of the child node. + * + * @param node Reference to a child XML_Node object + * + * @return Returns a reference to the added node + */ XML_Node& addChild(XML_Node& node); - XML_Node& addChild(std::string name); + + //! Add a child node to the current node with a specified name + /*! + * This will add an XML_Node as a child to the current node. + * The node will be blank except for the specified name. + * + * @param sname Name of the new child + * + * @return Returns a reference to the added node + */ + XML_Node& addChild(const std::string sname); + XML_Node& addChild(std::string name, std::string value); XML_Node& addChild(std::string name, double value, std::string fmt="%g"); void removeChild(XML_Node* node);