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:
parent
3933fb5264
commit
e65617c5e3
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user