38 m_msg = fmt::format(
"Error in XML file '{}' at line {}.\n", file, line);
70 const std::string& filename,
int line) :
72 m_msg += fmt::format(
"<{}> paired with </{}>.\n", opentag, closetag);
76 return "XML_TagMismatch";
98 std::string child,
const std::string& filename,
int line) :
100 m_msg += fmt::format(
"The XML Node <{}> does not contain a required " 101 "child node named <{}>.\nExisting children are named:\n",
104 m_msg += fmt::format(
" <{}>\n", cnode->name());
109 return "XML_NoChild";
115 XML_Reader::XML_Reader(std::istream& input) :
137 std::string::size_type istart = 0)
139 size_t icurrent = istart;
141 size_t iloc = s.find(q, icurrent);
145 char cm1 = s[iloc-1];
147 if (iloc >= (s.size() -1)) {
159 const char q1 =
'\'';
163 string::size_type iloc1, iloc2, ilocStart = 0;
186 rstring = s.substr(ilocStart + 1, iloc1 - 1);
189 return static_cast<int>(iloc1)+1;
193 std::map<std::string, std::string>& attribs)
const 195 string s = ba::trim_copy(tag);
196 size_t iloc = s.find(
' ');
198 name = s.substr(0, iloc);
199 s = ba::trim_copy(s.substr(iloc+1,s.size()));
200 if (s[s.size()-1] ==
'/') {
210 string attr = ba::trim_copy(s.substr(0,iloc));
214 s = ba::trim_copy(s.substr(iloc+1,s.size()));
219 if (iloc < s.size()) {
220 s = ba::trim_copy(s.substr(iloc,s.size()));
234 bool incomment =
false;
237 if (
m_s.eof() || (
getchr(ch), ch ==
'<')) {
241 char ch1 =
' ', ch2 =
' ';
251 if (ch1 ==
'-' && ch2 ==
'!') {
255 }
else if (ch ==
'>') {
257 if (ch1 ==
'-' && ch2 ==
'-') {
291 }
else if (ch !=
' ') {
298 if (front && lastch ==
' ' && ch ==
' ') {
304 return ba::trim_copy(tag);
328 m_iscomment(right.m_iscomment),
329 m_linenum(right.m_linenum)
337 XML_Node& XML_Node::operator=(
const XML_Node& right)
339 if (&right !=
this) {
340 for (
size_t i = 0; i <
m_children.size(); i++) {
352 XML_Node::~XML_Node()
355 writelog(
"XML_Node::~XML_Node: deleted a locked XML_Node: "+
name());
357 for (
size_t i = 0; i <
m_children.size(); i++) {
367 for (
size_t i = 0; i <
m_children.size(); i++) {
384 addChild(
"comment", comment);
401 XML_Node& XML_Node::addChild(
const std::string& sname)
406 XML_Node& XML_Node::addChild(
const std::string& name,
const std::string& value)
413 XML_Node& XML_Node::addChild(
const std::string& name,
const doublereal value,
414 const std::string& fmt)
439 if (
m_name ==
"comment") {
446 m_value = ba::trim_copy(fmt::sprintf(fmt, val));
461 return std::atoi(
m_value.c_str());
480 const doublereal vvalue,
const std::string& fmt)
487 m_attribs[aattrib] = fmt::format(
"{}", vvalue);
492 m_attribs[aattrib] = fmt::format(
"{}", vvalue);
502 return getValue<string,string>(
m_attribs, attr,
"");
558 if (discardComments) {
560 for (
size_t i = 0; i <
m_children.size(); i++) {
581 string msg=
"XML_Node "+
name()+
" is required to have an attribute named " + a +
582 " with the value \"" + v +
"\", but instead the value is \"" +
attrib(a);
587 const std::string& idTarget)
const 590 std::string idattrib =
id();
591 if (
name() == nameTarget && (idTarget ==
"" || idTarget == idattrib)) {
594 for (
size_t n = 0; n <
m_children.size(); n++) {
596 if (sc->
name() == nameTarget) {
597 if (idTarget ==
"") {
601 if (idTarget == idattrib) {
606 for (
size_t n = 0; n <
m_children.size(); n++) {
608 scResult = sc->
findNameID(nameTarget, idTarget);
617 const std::string& idTarget,
const int index_i)
const 620 std::string idattrib =
id();
621 std::string ii =
attrib(
"index");
622 std::string index_s = fmt::format(
"{}", index_i);
624 if (
name() == nameTarget && (idTarget ==
"" || idTarget == idattrib) && index_s == ii) {
627 for (
size_t n = 0; n <
m_children.size(); n++) {
629 if (sc->
name() == nameTarget) {
631 int indexR = atoi(ii.c_str());
633 if ((idTarget == idattrib || idTarget ==
"") && index_s == ii) {
651 for (
size_t i = 0; i <
nChildren(); i++) {
662 const std::string& val,
int depth)
const 669 for (
size_t i = 0; i < n; i++) {
685 for (
size_t i = 0; i <
nChildren(); i++) {
701 for (
size_t i = 0; i <
nChildren(); i++) {
713 s <<
"<?xml version=\"1.0\"?>" << endl;
718 ifstream fin(filename);
721 "Unable to open file '{}' for reading.", filename);
723 build(fin, filename);
733 map<string, string> node_attribs;
734 string nm = r.
readTag(node_attribs);
743 if (nm[nm.size() - 1] ==
'/') {
744 string nm2 = nm.substr(0,nm.size()-1);
749 node = &node->addChild(nm2);
752 node->
attribs() = node_attribs;
755 }
else if (nm[0] !=
'/') {
756 if (nm[0] !=
'!' && nm[0] !=
'-' && nm[0] !=
'?') {
761 node = &node->addChild(nm);
764 node->
attribs() = node_attribs;
766 }
else if (nm.substr(0,2) ==
"--") {
767 if (nm.substr(nm.size()-2,2) ==
"--") {
772 if (node->
name() != nm.substr(1,nm.size()-1)) {
792 const vector<XML_Node*> &vsc = node_dest->
children();
793 for (
size_t n = 0; n <
m_children.size(); n++) {
798 for (
size_t idc = 0; idc < ndc; idc++) {
818 node_dest->addChild(sc->
name());
836 const vector<XML_Node*> &vsc = node_dest->
children();
838 for (
size_t n = 0; n <
m_children.size(); n++) {
842 node_dest->addChild(sc->
name());
851 for (
size_t i = 0; i <
m_children.size(); i++) {
859 for (
size_t i = 0; i <
m_children.size(); i++) {
866 std::vector<XML_Node*> children_;
867 for (
size_t i = 0; i <
nChildren(); i++) {
869 children_.push_back(&
child(i));
879 size_t iloc = loc.find(
'/');
881 string cname = loc.substr(0,iloc);
882 loc = loc.substr(iloc+1, loc.size());
885 return i->second->child(loc);
908 string indent(level,
' ');
913 s << endl << indent <<
"<!--";
925 s << indent <<
"<" <<
m_name;
927 s <<
" " << attr.first <<
"=\"" << attr.second <<
"\"";
936 string::size_type ieol = vv.find(
'\n');
939 ieol = vv.find(
'\n');
942 s << endl << indent <<
" ";
944 size_t jf = ieol - 1;
945 for (
int j = 0; j < (int) ieol; j++) {
946 if (! isspace(vv[j])) {
951 s << endl << indent <<
" " << vv.substr(jf,ieol-jf);
953 vv = vv.substr(ieol+1);
955 size_t lll = vv.size() - 1;
958 for (
size_t j = 0; j < lll; j++) {
959 if (! isspace(vv[j])) {
965 s << endl << indent <<
" " << vv.substr(jf);
974 bool doNewLine =
false;
975 size_t ll =
m_value.size() - 1;
979 if (
m_name ==
"floatArray") {
987 s << endl << indent <<
" ";
991 if (doSpace && (! isspace(
m_value[0]))) {
998 if (doSpace && (! isspace(
m_value[ll]))) {
1002 s << endl << indent;
1006 if (numRecursivesAllowed > 0) {
1007 for (
size_t i = 0; i <
m_children.size(); i++) {
1009 m_children[i]->write_int(s,level + 2, numRecursivesAllowed - 1);
1013 s << endl << indent;
1015 s <<
"</" <<
m_name <<
">";
1021 write_int(s, level, numRecursivesAllowed);
1033 for (
size_t i = 0; i <
m_children.size(); i++) {
1039 const std::string& idtarget)
1045 if (root->
name() ==
"phase") {
1046 if (idtarget ==
"") {
1049 if (idtarget == root->
id()) {
1054 const vector<XML_Node*> &vsc = root->
children();
1055 for (
size_t n = 0; n < root->
nChildren(); n++) {
1057 if (sc->
name() ==
"phase") {
1058 if (idtarget ==
"") {
1061 if (idtarget == sc->
id()) {
1066 for (
size_t n = 0; n < root->
nChildren(); n++) {
void setName(const std::string &name_)
Sets the name of the XML node.
Class representing a specific type of XML file formatting error.
static string::size_type findUnbackslashed(const std::string &s, const char q, std::string::size_type istart=0)
Find the first position of a character, q, in string, s, which is not immediately preceded by the bac...
std::vector< XML_Node * > getChildren(const std::string &name) const
Get a vector of pointers to XML_Node containing all of the children of the current node which match t...
std::vector< XML_Node * > m_children
Vector of pointers to child nodes.
XML_Error(const std::string &file, int line)
Constructor.
std::string readTag(std::map< std::string, std::string > &attribs)
Reads an XML tag into a string.
std::string name() const
Returns the name of the XML node.
XML_Node * findXMLPhase(XML_Node *root, const std::string &idtarget)
Search an XML_Node tree for a named phase XML_Node.
virtual std::string getClass() const
Method overridden by derived classes to indicate their type.
virtual ~XML_Error()
destructor
const XML_Node * findByName(const std::string &nm, int depth=100000) const
This routine carries out a recursive search for an XML node based on the name of the node...
void clear()
Clear the current node and everything under it.
Various templated functions that carry out common vector operations (see Templated Utility Functions)...
void copyUnion(XML_Node *const node_dest) const
Copy all of the information in the current XML_Node tree into the destination XML_Node tree...
std::string operator()(const std::string &cname) const
The Overloaded parenthesis operator with one augment returns the value of an XML child node as a stri...
const size_t npos
index returned by functions to indicate "no position"
virtual std::string getMessage() const
Method overridden by derived classes to format the error message.
void writelog(const std::string &fmt, const Args &... args)
Write a formatted message to the screen.
integer int_value() const
Return the value of an XML node as a single int.
void unlock()
Unset the lock for this node and all of its children.
std::map< std::string, std::string > & attribs()
Returns a changeable value of the attributes map for the current node.
Class XML_Node is a tree-based representation of the contents of an XML file.
XML_TagMismatch(const std::string &opentag, const std::string &closetag, const std::string &filename, int line)
Constructor.
void write(std::ostream &s, const int level=0, int numRecursivesAllowed=60000) const
Write an XML subtree to an output stream.
This file contains definitions for utility functions and text for modules, inputfiles, logs, textlogs, (see Input File Handling, Diagnostic Output, and Writing messages to the screen).
std::map< std::string, std::string > m_attribs
Storage of attributes for a node.
bool hasAttrib(const std::string &a) const
Tests whether the current node has an attribute with a particular name.
bool isComment() const
Boolean function indicating whether a comment.
XML_Node * setParent(XML_Node *const p)
Sets the pointer for the parent node of the current node.
std::string m_value
Value of the XML node.
void addValue(const std::string &val)
Modify the value for the current node.
Class XML_Reader reads an XML file into an XML_Node object.
virtual std::string getClass() const
Method overridden by derived classes to indicate their type.
void _require(const std::string &a, const std::string &v) const
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.
void addComment(const std::string &comment)
Add a child node to the current node containing a comment.
const std::vector< XML_Node * > & children() const
Return an unchangeable reference to the vector of children of the current node.
int findQuotedString(const std::string &aline, std::string &rstring) const
Searches a string for the first occurrence of a valid quoted string.
bool m_locked
Lock for this node.
XML_Node * m_root
Pointer to the root XML_Node for the current node.
std::string m_filename
Name of the file from which this XML node was read.
void lock()
Set the lock for this node and all of its children.
bool m_iscomment
True if the current node is a comment node.
XML_Node(const std::string &nm="--", XML_Node *const parent=0)
Constructor for XML_Node, representing a tree structure.
Classes providing support for XML data files.
XML_Node * parent() const
Returns a pointer to the parent node of the current node.
Base class for exceptions thrown by Cantera classes.
std::string value() const
Return the value of an XML node as a string.
void build(const std::string &filename)
Populate the XML tree from an input file.
std::string m_msg
String message for the error.
XML_Node & mergeAsChild(XML_Node &node)
Merge an existing node as a child node to the current node.
XML_Node * m_parent
Pointer to the parent XML_Node for the current node.
void addAttribute(const std::string &attrib, const std::string &value)
Add or modify an attribute of the current node.
void copy(XML_Node *const node_dest) const
Copy all of the information in the current XML_Node tree into the destination XML_Node tree...
int lineNumber() const
Return the line number.
void setLineNumber(const int n)
Set the line number.
void parseTag(const std::string &tag, std::string &name, std::map< std::string, std::string > &attribs) const
parseTag parses XML tags, i.e., the XML elements that are in between angle brackets.
XML_Node * findNameID(const std::string &nameTarget, const std::string &idTarget) const
This routine carries out a recursive search for an XML node based on both the XML element name and th...
void setRoot(const XML_Node &root)
Set the root XML_Node value within the current node.
bool hasChild(const std::string &ch) const
Tests whether the current node has a child node with a particular name.
XML_Node & child(const size_t n) const
Return a changeable reference to the n'th child of the current node.
XML_Node & root() const
Return the root of the current XML_Node tree.
const std::map< std::string, std::string > & attribsConst() const
Returns an unchangeable value of the attributes map for the current node.
std::string m_name
XML node name of the node.
XML_Node * findNameIDIndex(const std::string &nameTarget, const std::string &idTarget, const int index) const
This routine carries out a search for an XML node based on both the XML element name and the attribut...
std::string readValue()
Return the value portion of an XML element.
void removeChild(const XML_Node *const node)
Remove a child from this node's list of children.
std::string attrib(const std::string &attr) const
Function returns the value of an attribute.
std::string operator[](const std::string &attr) const
The operator[] is overloaded to provide a lookup capability on attributes for the current XML element...
std::string id() const
Return the id attribute, if present.
Contains declarations for string manipulation functions within Cantera.
void writeHeader(std::ostream &s)
Write the header to the XML file to the specified ostream.
XML_Node * findByAttr(const std::string &attr, const std::string &val, int depth=100000) const
This routine carries out a recursive search for an XML node based on an attribute of each XML node...
Namespace for the Cantera kernel.
Classs representing a generic XML error condition.
void write_int(std::ostream &s, int level=0, int numRecursivesAllowed=60000) const
Write an XML subtree to an output stream.
doublereal fpValueCheck(const std::string &val)
Translate a string into one doublereal value, with error checking.
doublereal fp_value() const
Return the value of an XML node as a single double.
int m_linenum
The member data m_linenum.
size_t nChildren(bool discardComments=false) const
Return the number of children.
XML_NoChild(const XML_Node *p, const std::string &parent, std::string child, const std::string &filename, int line)
Constructor.
std::multimap< std::string, XML_Node * > m_childindex
Map containing an index between the node name and the pointer to the node.
XML_Node * findID(const std::string &id, const int depth=100) const
This routine carries out a recursive search for an XML node based on the XML element attribute...
std::istream & m_s
Input stream containing the XML file.
Class representing a specific type of XML file formatting error.
void getchr(char &ch)
Read a single character from the input stream and returns it.