Added: Debug print of the expanded XML-file content.

Fixed: Use InsertAfterChild instead of LinkEndChild when the included file
contains for than one tag, to ensure they are inserted into the right place.
This commit is contained in:
Knut Morten Okstad 2019-03-26 10:21:01 +01:00
parent 3933fb5264
commit e65617c5e3
2 changed files with 58 additions and 37 deletions

View File

@ -17,49 +17,59 @@
#include <algorithm>
void XMLInputBase::injectIncludeFiles (TiXmlElement* tag) const
/*!
\brief Helper method to load an XML file and print error message if failure.
*/
static bool loadXMLfile (TiXmlDocument& doc, const char* fileName)
{
static int nLevels = 0; ++nLevels;
bool foundIncludes = false;
if (doc.LoadFile(fileName))
return true;
std::cerr <<" *** SIMadmin::read: Failed to load \""<< fileName
<<"\".\n\tError at line "<< doc.ErrorRow() <<": "
<< doc.ErrorDesc() << std::endl;
return false;
}
bool XMLInputBase::injectIncludeFiles (TiXmlElement* tag, bool verbose) const
{
static int nLevels = 0;
std::string spaces(2*(nLevels++),' ');
bool foundIncludes = false, status = true;
TiXmlElement* elem = tag->FirstChildElement();
for (; elem; elem = elem->NextSiblingElement())
for (; elem && status; elem = elem->NextSiblingElement())
if (strcasecmp(elem->Value(),"include"))
this->injectIncludeFiles(elem);
status = this->injectIncludeFiles(elem,verbose);
else if (elem->FirstChild() && elem->FirstChild()->Value()) {
TiXmlDocument doc;
if (doc.LoadFile(elem->FirstChild()->Value())) {
for (int i = 1; i < nLevels; i++) IFEM::cout <<" ";
IFEM::cout <<"Loaded included file "<< elem->FirstChild()->Value()
<< std::endl;
elem = tag->ReplaceChild(elem,*doc.RootElement())->ToElement();
TiXmlElement* elem2 = doc.RootElement()->NextSiblingElement();
for (; elem2; elem2 = elem2->NextSiblingElement())
tag->LinkEndChild(new TiXmlElement(*elem2));
if ((status = loadXMLfile(doc,elem->FirstChild()->Value()))) {
if (verbose)
IFEM::cout << spaces <<"Loaded included file "
<< elem->FirstChild()->Value() << std::endl;
TiXmlElement* e2 = doc.RootElement();
TiXmlNode* n2 = elem = tag->ReplaceChild(elem,*e2)->ToElement();
for (e2 = e2->NextSiblingElement(); e2; e2 = e2->NextSiblingElement())
n2 = tag->InsertAfterChild(n2,*e2);
foundIncludes = true;
}
else
std::cerr <<" *** SIMadmin::read: Failed to load \""
<< elem->FirstChild()->Value()
<<"\".\n\tError at line "<< doc.ErrorRow() <<": "
<< doc.ErrorDesc() << std::endl;
}
if (foundIncludes)
this->injectIncludeFiles(tag);
if (foundIncludes && status)
status = this->injectIncludeFiles(tag,verbose);
--nLevels;
return status;
}
bool XMLInputBase::readXML (const char* fileName, bool verbose)
{
TiXmlDocument doc;
if (!doc.LoadFile(fileName)) {
std::cerr <<" *** SIMadmin::read: Failed to load \""<< fileName
<<"\".\n\tError at line "<< doc.ErrorRow() <<": "
<< doc.ErrorDesc() << std::endl;
if (!loadXMLfile(doc,fileName))
return false;
}
const TiXmlElement* tag = doc.RootElement();
if (!tag || strcmp(tag->Value(),"simulation")) {
@ -71,10 +81,18 @@ bool XMLInputBase::readXML (const char* fileName, bool verbose)
if (verbose)
IFEM::cout <<"\nParsing input file "<< fileName << std::endl;
this->injectIncludeFiles(const_cast<TiXmlElement*>(tag));
if (!this->injectIncludeFiles(const_cast<TiXmlElement*>(tag),verbose))
return false;
#ifdef SP_DEBUG
if (verbose) {
std::cout <<"\nHere is the input-file content:"<< std::endl;
doc.Print();
}
#endif
std::vector<const TiXmlElement*> parsed;
if (!handlePriorityTags(doc.RootElement(),parsed,verbose))
if (!this->handlePriorityTags(doc.RootElement(),parsed,verbose))
return false;
for (tag = tag->FirstChildElement(); tag; tag = tag->NextSiblingElement())
@ -102,8 +120,9 @@ bool XMLInputBase::handlePriorityTags (const TiXmlElement* base,
const char** q = this->getPrioritizedTags();
if (!q) return true; // No prioritized tags defined
for (const TiXmlElement* elem = 0; *q; q++)
if ((elem = base->FirstChildElement(*q))) {
while (*q) {
const TiXmlElement* elem = base->FirstChildElement(*(q++));
if (elem) {
if (verbose)
IFEM::cout <<"\nParsing <"<< elem->Value() <<">"<< std::endl;
if (!this->parse(elem)) {
@ -113,6 +132,7 @@ bool XMLInputBase::handlePriorityTags (const TiXmlElement* base,
}
parsed.push_back(elem);
}
}
return true;
}

View File

@ -7,7 +7,7 @@
//!
//! \author Arne Morten Kvarving / SINTEF
//!
//! \brief Base class for xml input parsing functionality.
//! \brief Base class for XML input parsing functionality.
//!
//==============================================================================
@ -22,7 +22,7 @@ class TiXmlElement;
/*!
\brief Base class for XML based input file parsing.
\details This class is inherited by SIMadmin for input parsing handling,
and is also used in applications for pre-parsing of the input file.
and can also be used by applications for pre-parsing of the input file.
*/
class XMLInputBase
@ -30,20 +30,21 @@ class XMLInputBase
public:
//! \brief Reads an XML input file.
//! \param[in] fileName File to read
//! \param[in] verbose True to print the tags being parsed to output
//! \param[in] verbose If \e true, print the tags being parsed
bool readXML(const char* fileName, bool verbose = true);
protected:
//! \brief Parses a data section from an XML element.
virtual bool parse(const TiXmlElement* elem) = 0;
//! \brief Recursive helper method for processing the \a include XML-tags.
void injectIncludeFiles(TiXmlElement* tag) const;
//! \brief Returns a list of prioritized XML-tags.
virtual const char** getPrioritizedTags() const { return nullptr; }
private:
//! \brief Handles the parsing order for certain XML-tags.
//! \param[in] base The base tag containing the elements to be prioritized
//! \param[out] parsed Vector of XML-elements that was parsed
//! \param verbose True to print the tags being parsed to output
//! \param[in] verbose If \e true, print the tags being parsed
//!
//! \details Certain tags need to be parsed before others. This method takes
//! care of this. It is called by the \a readXML method in order to read the
@ -55,8 +56,8 @@ protected:
std::vector<const TiXmlElement*>& parsed,
bool verbose);
//! \brief Returns a list of prioritized XML-tags.
virtual const char** getPrioritizedTags() const { return nullptr; }
//! \brief Recursive helper method for processing the \a include XML-tags.
bool injectIncludeFiles(TiXmlElement* tag, bool verbose) const;
};
#endif