diff --git a/include/cantera/base/xml.h b/include/cantera/base/xml.h index e8a8ae61c..f97ee1a80 100644 --- a/include/cantera/base/xml.h +++ b/include/cantera/base/xml.h @@ -579,8 +579,9 @@ public: * routine is called by the root XML_Node object. * * @param f Input stream containing the ascii input file + * @param filename Name of the input file, used in error messages */ - void build(std::istream& f); + void build(std::istream& f, const std::string& filename="[unknown]"); //! Copy all of the information in the current XML_Node tree into the //! destination XML_Node tree, doing a union operation as we go @@ -648,6 +649,10 @@ protected: */ std::string m_value; + //! Name of the file from which this XML node was read. Only populated for + //! the root node. + std::string m_filename; + //! Map containing an index between the node name and the //! pointer to the node /*! diff --git a/src/base/application.cpp b/src/base/application.cpp index bf4acd061..8867c06a6 100644 --- a/src/base/application.cpp +++ b/src/base/application.cpp @@ -220,7 +220,7 @@ XML_Node* Application::get_XML_File(const std::string& file, int debug) if (ext != ".xml" && ext != ".ctml") { // Assume that we are trying to open a cti file. Do the conversion to XML. std::stringstream phase_xml(ct2ctml_string(path)); - x->build(phase_xml); + x->build(phase_xml, path); } else { x->build(path); } @@ -245,7 +245,7 @@ XML_Node* Application::get_XML_from_string(const std::string& text) s << ct_string2ctml_string(text.substr(start)); } entry.first = new XML_Node(); - entry.first->build(s); + entry.first->build(s, "[string]"); return entry.first; } diff --git a/src/base/xml.cpp b/src/base/xml.cpp index deaea326a..7200a8a7d 100644 --- a/src/base/xml.cpp +++ b/src/base/xml.cpp @@ -31,13 +31,8 @@ protected: * * @param line Number number where the error occurred. */ - XML_Error(int line=0) : - m_line(line), - m_msg("Error in XML file") { - if (line > 0) { - m_msg += fmt::format(" at line {}", line+1); - } - m_msg += ".\n"; + XML_Error(const std::string& file, int line) { + m_msg = fmt::format("Error in XML file '{}' at line {}.\n", file, line); } virtual std::string getMessage() const { @@ -48,9 +43,6 @@ protected: virtual ~XML_Error() throw() { } - //! Line number of the file - int m_line; - //! String message for the error std::string m_msg; }; @@ -71,9 +63,9 @@ public: * @param line Line number where the error occurred. */ XML_TagMismatch(const std::string& opentag, const std::string& closetag, - int line=0) : - XML_Error(line) { - m_msg += "<" + opentag + "> paired with .\n"; + const std::string& filename, int line) : + XML_Error(filename, line) { + m_msg += fmt::format("<{}> paired with .\n", opentag, closetag); } virtual std::string getClass() const { @@ -98,8 +90,8 @@ public: * @param line Line number where the error occurred. */ XML_NoChild(const XML_Node* p, const std::string& parent, - std::string child, int line=0) : - XML_Error(line) { + std::string child, const std::string& filename, int line) : + XML_Error(filename, line) { m_msg += fmt::format("The XML Node <{}> does not contain a required " "child node named <{}>.\nExisting children are named:\n", parent, child); @@ -723,11 +715,12 @@ void XML_Node::build(const std::string& filename) throw CanteraError("XML_Node::build", "Unable to open file '{}' for reading.", filename); } - build(fin); + build(fin, filename); } -void XML_Node::build(std::istream& f) +void XML_Node::build(std::istream& f, const std::string& filename) { + m_filename = filename; XML_Reader r(f); XML_Node* node = this; bool first = true; @@ -772,7 +765,8 @@ void XML_Node::build(std::istream& f) } } else { if (node->name() != nm.substr(1,nm.size()-1)) { - throw XML_TagMismatch(node->name(), nm.substr(1,nm.size()-1), lnum); + throw XML_TagMismatch(node->name(), nm.substr(1,nm.size()-1), + root().m_filename, lnum); } node = node->parent(); } @@ -885,14 +879,16 @@ XML_Node& XML_Node::child(const std::string& aloc) const if (i != m_childindex.end()) { return i->second->child(loc); } else { - throw XML_NoChild(this, m_name, cname, lineNumber()); + throw XML_NoChild(this, m_name, cname, root().m_filename, + lineNumber()); } } else { auto i = m_childindex.find(loc); if (i != m_childindex.end()) { return *(i->second); } else { - throw XML_NoChild(this, m_name, loc, lineNumber()); + throw XML_NoChild(this, m_name, loc, root().m_filename, + lineNumber()); } } } diff --git a/src/clib/ctxml.cpp b/src/clib/ctxml.cpp index 208011f36..00350c333 100644 --- a/src/clib/ctxml.cpp +++ b/src/clib/ctxml.cpp @@ -89,12 +89,7 @@ extern "C" { try { writelog("WARNING: xml_build called. Use get_XML_File instead."); string path = findInputFile(file); - ifstream f(path); - if (!f) { - throw CanteraError("xml_build", - "file "+string(file)+" not found."); - } - XmlCabinet::item(i).build(f); + XmlCabinet::item(i).build(path); return 0; } catch (...) { return handleAllExceptions(-1, ERR); diff --git a/src/oneD/OneDim.cpp b/src/oneD/OneDim.cpp index 7fdc8e33e..dc75404e8 100644 --- a/src/oneD/OneDim.cpp +++ b/src/oneD/OneDim.cpp @@ -421,7 +421,7 @@ void OneDim::save(const std::string& fname, std::string id, XML_Node root("ctml"); ifstream fin(fname); if (fin) { - root.build(fin); + root.build(fin, fname); // Remove existing solution with the same id XML_Node* same_ID = root.findID(id); if (same_ID) {