39 m_msg = fmt::format(
"Error in XML file '{}' at line {}.\n", file, line);
71 const std::string& filename,
int line) :
73 m_msg += fmt::format(
"<{}> paired with </{}>.\n", opentag, closetag);
77 return "XML_TagMismatch";
99 std::string child,
const std::string& filename,
int line) :
101 m_msg += fmt::format(
"The XML Node <{}> does not contain a required "
102 "child node named <{}>.\nExisting children are named:\n",
105 m_msg += fmt::format(
" <{}>\n", cnode->name());
110 return "XML_NoChild";
138 std::string::size_type istart = 0)
140 size_t icurrent = istart;
142 size_t iloc = s.find(q, icurrent);
146 char cm1 = s[iloc-1];
148 if (iloc >= (s.size() -1)) {
160 const char q1 =
'\'';
164 string::size_type iloc1, iloc2, ilocStart = 0;
187 rstring = s.substr(ilocStart + 1, iloc1 - 1);
190 return static_cast<int>(iloc1)+1;
194 std::map<std::string, std::string>& attribs)
const
197 size_t iloc = s.find(
' ');
199 name = s.substr(0, iloc);
200 s =
trimCopy(s.substr(iloc+1,s.size()));
201 if (s[s.size()-1] ==
'/') {
211 string attr =
trimCopy(s.substr(0,iloc));
215 s =
trimCopy(s.substr(iloc+1,s.size()));
220 if (iloc < s.size()) {
221 s =
trimCopy(s.substr(iloc,s.size()));
235 bool incomment =
false;
238 if (
m_s.eof() || (
getchr(ch), ch ==
'<')) {
242 char ch1 =
' ', ch2 =
' ';
252 if (ch1 ==
'-' && ch2 ==
'!') {
256 }
else if (ch ==
'>') {
258 if (ch1 ==
'-' && ch2 ==
'-') {
292 }
else if (ch !=
' ') {
299 if (front && lastch ==
' ' && ch ==
' ') {
329 m_iscomment(right.m_iscomment),
330 m_linenum(right.m_linenum)
338XML_Node& XML_Node::operator=(
const XML_Node& right)
340 if (&right !=
this) {
341 for (
size_t i = 0; i <
m_children.size(); i++) {
356 writelog(
"XML_Node::~XML_Node: deleted a locked XML_Node: "+
name());
358 for (
size_t i = 0; i <
m_children.size(); i++) {
368 for (
size_t i = 0; i <
m_children.size(); i++) {
397XML_Node& XML_Node::addChild(
const std::string& sname)
402XML_Node& XML_Node::addChild(
const std::string& name,
const std::string& value)
409XML_Node& XML_Node::addChild(
const std::string& name,
const doublereal value,
410 const std::string&
fmt)
426 addChild(
"comment", comment);
432 if (
m_name ==
"comment") {
464 return std::atoi(
m_value.c_str());
473 const doublereal vvalue,
const std::string&
fmt)
480 m_attribs[aattrib] = fmt::format(
"{}", vvalue);
485 m_attribs[aattrib] = fmt::format(
"{}", vvalue);
495 return getValue<string,string>(
m_attribs, attr,
"");
559 if (discardComments) {
561 for (
size_t i = 0; i <
m_children.size(); i++) {
582 string msg=
"XML_Node "+
name()+
" is required to have an attribute named " + a +
583 " with the value \"" + v +
"\", but instead the value is \"" +
attrib(a);
588 const std::string& idTarget)
const
591 std::string idattrib =
id();
592 if (
name() == nameTarget && (idTarget ==
"" || idTarget == idattrib)) {
595 for (
size_t n = 0; n <
m_children.size(); n++) {
597 if (sc->
name() == nameTarget) {
598 if (idTarget ==
"") {
602 if (idTarget == idattrib) {
607 for (
size_t n = 0; n <
m_children.size(); n++) {
609 scResult = sc->
findNameID(nameTarget, idTarget);
618 const std::string& idTarget,
const int index_i)
const
621 std::string idattrib =
id();
622 std::string ii =
attrib(
"index");
623 std::string index_s = fmt::format(
"{}", index_i);
625 if (
name() == nameTarget && (idTarget ==
"" || idTarget == idattrib) && index_s == ii) {
628 for (
size_t n = 0; n <
m_children.size(); n++) {
630 if (sc->
name() == nameTarget) {
632 int indexR = atoi(ii.c_str());
634 if ((idTarget == idattrib || idTarget ==
"") && index_s == ii) {
652 for (
size_t i = 0; i <
nChildren(); i++) {
663 const std::string& val,
int depth)
const
670 for (
size_t i = 0; i < n; i++) {
686 for (
size_t i = 0; i <
nChildren(); i++) {
702 for (
size_t i = 0; i <
nChildren(); i++) {
714 std::vector<XML_Node*> children_;
715 for (
size_t i = 0; i <
nChildren(); i++) {
717 children_.push_back(&
child(i));
727 size_t iloc = loc.find(
'/');
729 string cname = loc.substr(0,iloc);
730 loc = loc.substr(iloc+1, loc.size());
733 return i->second->child(loc);
758 for (
size_t i = 0; i <
m_children.size(); i++) {
765 ifstream fin(filename);
768 "Unable to open file '{}' for reading.", filename);
770 build(fin, filename);
776 "\nThe CTI and XML input file formats are deprecated and will be removed in\n"
777 "Cantera 3.0. Use 'cti2yaml.py' or 'ctml2yaml.py' to convert CTI or XML input\n"
778 "files to the YAML format. See https://cantera.org/tutorials/legacy2yaml.html\n"
779 "for more information.");
785 map<string, string> node_attribs;
786 string nm = r.
readTag(node_attribs);
795 if (nm[nm.size() - 1] ==
'/') {
796 string nm2 = nm.substr(0,nm.size()-1);
801 node = &node->addChild(nm2);
804 node->
attribs() = node_attribs;
807 }
else if (nm[0] !=
'/') {
808 if (nm[0] !=
'!' && nm[0] !=
'-' && nm[0] !=
'?') {
813 node = &node->addChild(nm);
816 node->
attribs() = node_attribs;
818 }
else if (nm.substr(0,2) ==
"--") {
819 if (nm.substr(nm.size()-2,2) ==
"--") {
824 if (node->
name() != nm.substr(1,nm.size()-1)) {
844 const vector<XML_Node*> &vsc = node_dest->
children();
845 for (
size_t n = 0; n <
m_children.size(); n++) {
850 for (
size_t idc = 0; idc < ndc; idc++) {
870 node_dest->addChild(sc->
name());
888 const vector<XML_Node*> &vsc = node_dest->
children();
890 for (
size_t n = 0; n <
m_children.size(); n++) {
894 node_dest->addChild(sc->
name());
903 for (
size_t i = 0; i <
m_children.size(); i++) {
911 for (
size_t i = 0; i <
m_children.size(); i++) {
918 s <<
"<?xml version=\"1.0\"?>" << endl;
927 string indent(level,
' ');
932 s << endl << indent <<
"<!--";
944 s << indent <<
"<" <<
m_name;
946 s <<
" " << attr.first <<
"=\"" << attr.second <<
"\"";
955 string::size_type ieol = vv.find(
'\n');
958 ieol = vv.find(
'\n');
961 s << endl << indent <<
" ";
963 size_t jf = ieol - 1;
964 for (
int j = 0; j < (int) ieol; j++) {
965 if (! isspace(vv[j])) {
970 s << endl << indent <<
" " << vv.substr(jf,ieol-jf);
972 vv = vv.substr(ieol+1);
974 size_t lll = vv.size() - 1;
977 for (
size_t j = 0; j < lll; j++) {
978 if (! isspace(vv[j])) {
984 s << endl << indent <<
" " << vv.substr(jf);
993 bool doNewLine =
false;
994 size_t ll =
m_value.size() - 1;
998 if (
m_name ==
"floatArray") {
1006 s << endl << indent <<
" ";
1010 if (doSpace && (! isspace(
m_value[0]))) {
1017 if (doSpace && (! isspace(
m_value[ll]))) {
1021 s << endl << indent;
1025 if (numRecursivesAllowed > 0) {
1026 for (
size_t i = 0; i <
m_children.size(); i++) {
1028 m_children[i]->write_int(s,level + 2, numRecursivesAllowed - 1);
1032 s << endl << indent;
1034 s <<
"</" <<
m_name <<
">";
1041 "\nThe CTI and XML input file formats are deprecated and will be removed in\n"
1042 "Cantera 3.0. Use 'cti2yaml.py' or 'ctml2yaml.py' to convert CTI or XML input\n"
1043 "files to the YAML format. See https://cantera.org/tutorials/legacy2yaml.html\n"
1044 "for more information.");
1045 write_int(s, level, numRecursivesAllowed);
1050 const std::string& phaseId)
1056 if (root->
name() ==
"phase") {
1057 if (phaseId ==
"") {
1060 if (phaseId == root->
id()) {
1065 const vector<XML_Node*> &vsc = root->
children();
1066 for (
size_t n = 0; n < root->
nChildren(); n++) {
1068 if (sc->
name() ==
"phase") {
1069 if (phaseId ==
"") {
1072 if (phaseId == sc->
id()) {
1077 for (
size_t n = 0; n < root->
nChildren(); n++) {
Base class for exceptions thrown by Cantera classes.
Class representing a generic XML error condition.
virtual std::string getMessage() const
Method overridden by derived classes to format the error message.
virtual ~XML_Error()
destructor
std::string m_msg
String message for the error.
XML_Error(const std::string &file, int line)
Constructor.
Class representing a specific type of XML file formatting error.
virtual std::string getClass() const
Method overridden by derived classes to indicate their type.
XML_NoChild(const XML_Node *p, const std::string &parent, std::string child, const std::string &filename, int line)
Constructor.
Class XML_Node is a tree-based representation of the contents of an XML file.
void removeChild(const XML_Node *const node)
Remove a child from this node's list of children.
std::map< std::string, std::string > m_attribs
Storage of attributes for a node.
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.
void setName(const std::string &name_)
Sets the name of the XML node.
std::string attrib(const std::string &attr) const
Function returns the value of an attribute.
XML_Node(const std::string &nm="--", XML_Node *const parent=0)
Constructor for XML_Node, representing a tree structure.
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,...
std::string name() const
Returns the name of the XML node.
bool hasChild(const std::string &ch) const
Tests whether the current node has a child node with a particular name.
int lineNumber() const
Return the line number.
void build(const std::string &filename)
Populate the XML tree from an input file.
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...
XML_Node * m_root
Pointer to the root XML_Node for the current node.
XML_Node & mergeAsChild(XML_Node &node)
Merge an existing node as a child node to the current node.
void write_int(std::ostream &s, int level=0, int numRecursivesAllowed=60000) const
Write an XML subtree to an output stream.
std::string id() const
Return the id attribute, if present.
XML_Node & root() const
Return the root of the current XML_Node tree.
void addValue(const std::string &val)
Modify the value for the current node.
std::map< std::string, std::string > & attribs()
Returns a changeable value of the attributes map for the current node.
int m_linenum
The member data m_linenum.
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.
bool m_locked
Lock for this node.
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,...
bool m_iscomment
True if the current node is a comment node.
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.
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.
void write(std::ostream &s, const int level=0, int numRecursivesAllowed=60000) const
Write an XML subtree to an output stream.
void _require(const std::string &a, const std::string &v) const
Require that the current XML node has an attribute named by the first argument, a,...
doublereal fp_value() const
Return the value of an XML node as a single double.
void writeHeader(std::ostream &s)
Write the header to the XML file to the specified ostream.
void lock()
Set the lock for this node and all of its children.
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 "id".
std::multimap< std::string, XML_Node * > m_childindex
Map containing an index between the node name and the pointer to the node.
const std::vector< XML_Node * > & children() const
Return an unchangeable reference to the vector of children of the current 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 the XML element name, the attribute ID and...
void setLineNumber(const int n)
Set the line number.
XML_Node * parent() const
Returns a pointer to the parent node of the current node.
std::string m_filename
Name of the file from which this XML node was read.
void clear()
Clear the current node and everything under it.
void addComment(const std::string &comment)
Add a child node to the current node containing a comment.
const std::map< std::string, std::string > & attribsConst() const
Returns an unchangeable value of the attributes map for the current node.
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::string value() const
Return the value of an XML node as a string.
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...
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 m_value
Value of the XML node.
size_t nChildren(bool discardComments=false) const
Return the number of children.
XML_Node * setParent(XML_Node *const p)
Sets the pointer for the parent node of the current node.
std::string m_name
XML node name of the node.
XML_Node & child(const size_t n) const
Return a changeable reference to the n'th child of the current node.
void setRoot(const XML_Node &root)
Set the root XML_Node value within the current node.
std::vector< XML_Node * > m_children
Vector of pointers to child nodes.
bool isComment() const
Boolean function indicating whether a comment.
bool hasAttrib(const std::string &a) const
Tests whether the current node has an attribute with a particular name.
Class XML_Reader reads an XML file into an XML_Node object.
std::string readTag(std::map< std::string, std::string > &attribs)
Reads an XML tag into a string.
void getchr(char &ch)
Read a single character from the input stream and returns it.
int findQuotedString(const std::string &aline, std::string &rstring) const
Searches a string for the first occurrence of a valid quoted string.
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_Reader(std::istream &input)
Sole Constructor for the XML_Reader class.
std::istream & m_s
Input stream containing the XML file.
std::string readValue()
Return the value portion of an XML element.
Class representing a specific type of XML file formatting error.
XML_TagMismatch(const std::string &opentag, const std::string &closetag, const std::string &filename, int line)
Constructor.
virtual std::string getClass() const
Method overridden by derived classes to indicate their type.
Definitions for the classes that are thrown when Cantera experiences an error condition (also contain...
This file contains definitions for utility functions and text for modules, inputfiles,...
void writelog(const std::string &fmt, const Args &... args)
Write a formatted message to the screen.
Namespace for the Cantera kernel.
const size_t npos
index returned by functions to indicate "no position"
XML_Node * findXMLPhase(XML_Node *root, const std::string &phaseId)
Search an XML_Node tree for a named phase XML_Node.
bool caseInsensitiveEquals(const std::string &input, const std::string &test)
Case insensitive equality predicate.
void warn_deprecated(const std::string &source, const AnyBase &node, const std::string &message)
A deprecation warning for syntax in an input file.
std::string trimCopy(const std::string &input)
Trim.
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...
doublereal fpValueCheck(const std::string &val)
Translate a string into one doublereal value, with error checking.
Versions 6.2.0 and 6.2.1 of fmtlib do not include this define before they include windows....
Contains declarations for string manipulation functions within Cantera.
Various templated functions that carry out common vector operations (see Templated Utility Functions)...
Classes providing support for XML data files.