diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 962440199..a7adb5125 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -347,6 +347,8 @@ set(SRCS
cmXMLParser.h
cmXMLSafe.cxx
cmXMLSafe.h
+ cmXMLWriter.cxx
+ cmXMLWriter.h
cmake.cxx
cmake.h
diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx
index ccb3e4406..e141b6019 100644
--- a/Source/CTest/cmCTestBuildHandler.cxx
+++ b/Source/CTest/cmCTestBuildHandler.cxx
@@ -18,7 +18,7 @@
#include "cmLocalGenerator.h"
#include "cmGlobalGenerator.h"
#include "cmGeneratedFileStream.h"
-#include "cmXMLSafe.h"
+#include "cmXMLWriter.h"
#include "cmFileTimeComparison.h"
#include "cmAlgorithms.h"
@@ -523,16 +523,17 @@ int cmCTestBuildHandler::ProcessHandler()
<< std::endl);
return -1;
}
- this->GenerateXMLHeader(xofs);
+ cmXMLWriter xml(xofs);
+ this->GenerateXMLHeader(xml);
if(this->UseCTestLaunch)
{
- this->GenerateXMLLaunched(xofs);
+ this->GenerateXMLLaunched(xml);
}
else
{
- this->GenerateXMLLogScraped(xofs);
+ this->GenerateXMLLogScraped(xml);
}
- this->GenerateXMLFooter(xofs, elapsed_build_time);
+ this->GenerateXMLFooter(xml, elapsed_build_time);
if (res != cmsysProcess_State_Exited || retVal || this->TotalErrors > 0)
{
@@ -552,17 +553,14 @@ int cmCTestBuildHandler::ProcessHandler()
}
//----------------------------------------------------------------------------
-void cmCTestBuildHandler::GenerateXMLHeader(std::ostream& os)
+void cmCTestBuildHandler::GenerateXMLHeader(cmXMLWriter& xml)
{
- this->CTest->StartXML(os, this->AppendXML);
- os << "\n"
- << "\t" << this->StartBuild << "\n"
- << "\t" <<
- static_cast(this->StartBuildTime)
- << "\n"
- << ""
- << cmXMLSafe(this->GetMakeCommand())
- << "" << std::endl;
+ this->CTest->StartXML(xml, this->AppendXML);
+ xml.StartElement("Build");
+ xml.Element("StartDateTime", this->StartBuild);
+ xml.Element("StartBuildTime",
+ static_cast(this->StartBuildTime));
+ xml.Element("BuildCommand", this->GetMakeCommand());
}
//----------------------------------------------------------------------------
@@ -591,7 +589,7 @@ private:
};
//----------------------------------------------------------------------------
-void cmCTestBuildHandler::GenerateXMLLaunched(std::ostream& os)
+void cmCTestBuildHandler::GenerateXMLLaunched(cmXMLWriter& xml)
{
if(this->CTestLaunchDir.empty())
{
@@ -632,12 +630,12 @@ void cmCTestBuildHandler::GenerateXMLLaunched(std::ostream& os)
for(Fragments::const_iterator fi = fragments.begin();
fi != fragments.end(); ++fi)
{
- this->GenerateXMLLaunchedFragment(os, fi->c_str());
+ xml.FragmentFile(fi->c_str());
}
}
//----------------------------------------------------------------------------
-void cmCTestBuildHandler::GenerateXMLLogScraped(std::ostream& os)
+void cmCTestBuildHandler::GenerateXMLLogScraped(cmXMLWriter& xml)
{
std::vector& ew = this->ErrorsAndWarnings;
std::vector::iterator it;
@@ -665,10 +663,9 @@ void cmCTestBuildHandler::GenerateXMLLogScraped(std::ostream& os)
{
numWarningsAllowed--;
}
- os << "\t<" << (cm->Error ? "Error" : "Warning") << ">\n"
- << "\t\t" << cm->LogLine << "\n"
- << "\t\t" << cmXMLSafe(cm->Text).Quotes(false)
- << "\n" << std::endl;
+ xml.StartElement(cm->Error ? "Error" : "Warning");
+ xml.Element("BuildLogLine", cm->LogLine);
+ xml.Element("Text", cm->Text);
std::vector::iterator rit;
for ( rit = this->ErrorWarningFileLineRegex.begin();
rit != this->ErrorWarningFileLineRegex.end(); ++ rit )
@@ -706,62 +703,48 @@ void cmCTestBuildHandler::GenerateXMLLogScraped(std::ostream& os)
{
if (!cm->SourceFile.empty())
{
- os << "\t\t" << cm->SourceFile << ""
- << std::endl;
+ xml.Element("SourceFile", cm->SourceFile);
}
if (!cm->SourceFileTail.empty())
{
- os << "\t\t" << cm->SourceFileTail
- << "" << std::endl;
+ xml.Element("SourceFileTail", cm->SourceFileTail);
}
if ( cm->LineNumber >= 0 )
{
- os << "\t\t" << cm->LineNumber
- << "" << std::endl;
+ xml.Element("SourceLineNumber", cm->LineNumber);
}
}
- os << "\t\t" << cmXMLSafe(cm->PreContext).Quotes(false)
- << "\n"
- << "\t\t" << cmXMLSafe(cm->PostContext).Quotes(false);
+ xml.Element("PreContext", cm->PreContext);
+ xml.StartElement("PostContext");
+ xml.Content(cm->PostContext);
// is this the last warning or error, if so notify
if ((cm->Error && !numErrorsAllowed) ||
(!cm->Error && !numWarningsAllowed))
{
- os << "\nThe maximum number of reported warnings or errors has been "
- "reached!!!\n";
+ xml.Content("\nThe maximum number of reported warnings or errors "
+ "has been reached!!!\n");
}
- os << "\n"
- << "\t\t0\n"
- << "" << (cm->Error ? "Error" : "Warning") << ">\n\n"
- << std::endl;
+ xml.EndElement(); // PostContext
+ xml.Element("RepeatCount", "0");
+ xml.EndElement(); // "Error" / "Warning"
}
}
}
//----------------------------------------------------------------------------
-void cmCTestBuildHandler::GenerateXMLFooter(std::ostream& os,
+void cmCTestBuildHandler::GenerateXMLFooter(cmXMLWriter& xml,
double elapsed_build_time)
{
- os << "\t\n\t\n"
- << "\t" << this->EndBuild << "\n"
- << "\t" << static_cast(this->EndBuildTime)
- << "\n"
- << "" << static_cast(elapsed_build_time/6)/10.0
- << ""
- << "" << std::endl;
- this->CTest->EndXML(os);
-}
+ xml.StartElement("Log");
+ xml.Attribute("Encoding", "base64");
+ xml.Attribute("Compression", "bin/gzip");
+ xml.EndElement(); // Log
-//----------------------------------------------------------------------------
-void cmCTestBuildHandler::GenerateXMLLaunchedFragment(std::ostream& os,
- const char* fname)
-{
- cmsys::ifstream fin(fname, std::ios::in | std::ios::binary);
- std::string line;
- while(cmSystemTools::GetLineFromStream(fin, line))
- {
- os << line << "\n";
- }
+ xml.Element("EndDateTime", this->EndBuild);
+ xml.Element("EndBuildTime", static_cast(this->EndBuildTime));
+ xml.Element("ElapsedMinutes", static_cast(elapsed_build_time/6)/10.0);
+ xml.EndElement(); // Build
+ this->CTest->EndXML(xml);
}
//----------------------------------------------------------------------------
diff --git a/Source/CTest/cmCTestBuildHandler.h b/Source/CTest/cmCTestBuildHandler.h
index d13d5cf35..2e9b92a70 100644
--- a/Source/CTest/cmCTestBuildHandler.h
+++ b/Source/CTest/cmCTestBuildHandler.h
@@ -22,6 +22,7 @@
#include
class cmMakefile;
+class cmXMLWriter;
/** \class cmCTestBuildHandler
* \brief A class that handles ctest -S invocations
@@ -86,11 +87,10 @@ private:
};
// generate the XML output
- void GenerateXMLHeader(std::ostream& os);
- void GenerateXMLLaunched(std::ostream& os);
- void GenerateXMLLogScraped(std::ostream& os);
- void GenerateXMLFooter(std::ostream& os, double elapsed_build_time);
- void GenerateXMLLaunchedFragment(std::ostream& os, const char* fname);
+ void GenerateXMLHeader(cmXMLWriter& xml);
+ void GenerateXMLLaunched(cmXMLWriter& xml);
+ void GenerateXMLLogScraped(cmXMLWriter& xml);
+ void GenerateXMLFooter(cmXMLWriter& xml, double elapsed_build_time);
bool IsLaunchedErrorFile(const char* fname);
bool IsLaunchedWarningFile(const char* fname);
diff --git a/Source/CTest/cmCTestCVS.cxx b/Source/CTest/cmCTestCVS.cxx
index ab363d016..0fb3fec57 100644
--- a/Source/CTest/cmCTestCVS.cxx
+++ b/Source/CTest/cmCTestCVS.cxx
@@ -13,7 +13,7 @@
#include "cmCTest.h"
#include "cmSystemTools.h"
-#include "cmXMLSafe.h"
+#include "cmXMLWriter.h"
#include
#include
@@ -266,13 +266,13 @@ void cmCTestCVS::LoadRevisions(std::string const& file,
}
//----------------------------------------------------------------------------
-void cmCTestCVS::WriteXMLDirectory(std::ostream& xml,
+void cmCTestCVS::WriteXMLDirectory(cmXMLWriter& xml,
std::string const& path,
Directory const& dir)
{
const char* slash = path.empty()? "":"/";
- xml << "\t\n"
- << "\t\t" << cmXMLSafe(path) << "\n";
+ xml.StartElement("Directory");
+ xml.Element("Name", path);
// Lookup the branch checked out in the working tree.
std::string branchFlag = this->ComputeBranchFlag(path);
@@ -298,11 +298,11 @@ void cmCTestCVS::WriteXMLDirectory(std::ostream& xml,
File f(fi->second, &revisions[0], &revisions[1]);
this->WriteXMLEntry(xml, path, fi->first, full, f);
}
- xml << "\t\n";
+ xml.EndElement(); // Directory
}
//----------------------------------------------------------------------------
-bool cmCTestCVS::WriteXMLUpdates(std::ostream& xml)
+bool cmCTestCVS::WriteXMLUpdates(cmXMLWriter& xml)
{
cmCTestLog(this->CTest, HANDLER_OUTPUT,
" Gathering version information (one . per updated file):\n"
diff --git a/Source/CTest/cmCTestCVS.h b/Source/CTest/cmCTestCVS.h
index 64e1747d1..f2c0a73bd 100644
--- a/Source/CTest/cmCTestCVS.h
+++ b/Source/CTest/cmCTestCVS.h
@@ -29,7 +29,7 @@ public:
private:
// Implement cmCTestVC internal API.
virtual bool UpdateImpl();
- virtual bool WriteXMLUpdates(std::ostream& xml);
+ virtual bool WriteXMLUpdates(cmXMLWriter& xml);
// Update status for files in each directory.
class Directory: public std::map {};
@@ -38,7 +38,7 @@ private:
std::string ComputeBranchFlag(std::string const& dir);
void LoadRevisions(std::string const& file, const char* branchFlag,
std::vector& revisions);
- void WriteXMLDirectory(std::ostream& xml, std::string const& path,
+ void WriteXMLDirectory(cmXMLWriter& xml, std::string const& path,
Directory const& dir);
// Parsing helper classes.
diff --git a/Source/CTest/cmCTestConfigureHandler.cxx b/Source/CTest/cmCTestConfigureHandler.cxx
index 2c2951d86..2e8aeb956 100644
--- a/Source/CTest/cmCTestConfigureHandler.cxx
+++ b/Source/CTest/cmCTestConfigureHandler.cxx
@@ -15,7 +15,7 @@
#include "cmCTest.h"
#include "cmGeneratedFileStream.h"
#include "cmake.h"
-#include "cmXMLSafe.h"
+#include "cmXMLWriter.h"
#include
@@ -89,28 +89,22 @@ int cmCTestConfigureHandler::ProcessHandler()
if ( os )
{
- this->CTest->StartXML(os, this->AppendXML);
- os << "\n"
- << "\t" << start_time << ""
- << std::endl
- << "\t" << start_time_time
- << "\n";
- os << "" << cCommand << ""
- << std::endl;
+ cmXMLWriter xml(os);
+ this->CTest->StartXML(xml, this->AppendXML);
+ xml.StartElement("Configure");
+ xml.Element("StartDateTime", start_time);
+ xml.Element("StartConfigureTime", start_time_time);
+ xml.Element("ConfigureCommand", cCommand);
cmCTestOptionalLog(this->CTest, DEBUG, "End" << std::endl, this->Quiet);
- os << "" << cmXMLSafe(output) << "" << std::endl;
- std::string end_time = this->CTest->CurrentTime();
- os << "\t" << retVal << "\n"
- << "\t" << end_time << "\n"
- << "\t" <<
- static_cast(cmSystemTools::GetTime())
- << "\n"
- << ""
- << static_cast(
- (cmSystemTools::GetTime() - elapsed_time_start)/6)/10.0
- << ""
- << "" << std::endl;
- this->CTest->EndXML(os);
+ xml.Element("Log", output);
+ xml.Element("ConfigureStatus", retVal);
+ xml.Element("EndDateTime", this->CTest->CurrentTime());
+ xml.Element("EndConfigureTime",
+ static_cast(cmSystemTools::GetTime()));
+ xml.Element("ElapsedMinutes", static_cast(
+ (cmSystemTools::GetTime() - elapsed_time_start)/6)/10.0);
+ xml.EndElement(); // Configure
+ this->CTest->EndXML(xml);
}
}
else
diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx
index 790e488bf..f92f19ad8 100644
--- a/Source/CTest/cmCTestCoverageHandler.cxx
+++ b/Source/CTest/cmCTestCoverageHandler.cxx
@@ -22,7 +22,7 @@
#include "cmMakefile.h"
#include "cmSystemTools.h"
#include "cmGeneratedFileStream.h"
-#include "cmXMLSafe.h"
+#include "cmXMLWriter.h"
#include
#include
@@ -185,14 +185,6 @@ bool cmCTestCoverageHandler::StartCoverageLogFile(
<< covLogFilename << std::endl);
return false;
}
- std::string local_start_time = this->CTest->CurrentTime();
- this->CTest->StartXML(covLogFile, this->AppendXML);
- covLogFile << "" << std::endl
- << "\t" << local_start_time << ""
- << "\t"
- << static_cast(cmSystemTools::GetTime())
- << ""
- << std::endl;
return true;
}
@@ -200,13 +192,6 @@ bool cmCTestCoverageHandler::StartCoverageLogFile(
void cmCTestCoverageHandler::EndCoverageLogFile(cmGeneratedFileStream& ostr,
int logFileCount)
{
- std::string local_end_time = this->CTest->CurrentTime();
- ostr << "\t" << local_end_time << "" << std::endl
- << "\t" <<
- static_cast(cmSystemTools::GetTime())
- << "" << std::endl
- << "" << std::endl;
- this->CTest->EndXML(ostr);
char covLogFilename[1024];
sprintf(covLogFilename, "CoverageLog-%d.xml", logFileCount);
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Close file: "
@@ -214,6 +199,25 @@ void cmCTestCoverageHandler::EndCoverageLogFile(cmGeneratedFileStream& ostr,
ostr.Close();
}
+//----------------------------------------------------------------------
+void cmCTestCoverageHandler::StartCoverageLogXML(cmXMLWriter& xml)
+{
+ this->CTest->StartXML(xml, this->AppendXML);
+ xml.StartElement("CoverageLog");
+ xml.Element("StartDateTime", this->CTest->CurrentTime());
+ xml.Element("StartTime",
+ static_cast(cmSystemTools::GetTime()));
+}
+
+//----------------------------------------------------------------------
+void cmCTestCoverageHandler::EndCoverageLogXML(cmXMLWriter& xml)
+{
+ xml.Element("EndDateTime", this->CTest->CurrentTime());
+ xml.Element("EndTime", static_cast(cmSystemTools::GetTime()));
+ xml.EndElement(); // CoverageLog
+ this->CTest->EndXML(xml);
+}
+
//----------------------------------------------------------------------
bool cmCTestCoverageHandler::ShouldIDoCoverage(const char* file,
const char* srcDir,
@@ -451,6 +455,8 @@ int cmCTestCoverageHandler::ProcessHandler()
}
cmGeneratedFileStream covSumFile;
cmGeneratedFileStream covLogFile;
+ cmXMLWriter covSumXML(covSumFile);
+ cmXMLWriter covLogXML(covLogFile);
if(!this->StartResultingXML(cmCTest::PartCoverage, "Coverage", covSumFile))
{
@@ -458,20 +464,21 @@ int cmCTestCoverageHandler::ProcessHandler()
"Cannot open coverage summary file." << std::endl);
return -1;
}
+ covSumFile.setf(std::ios::fixed, std::ios::floatfield);
+ covSumFile.precision(2);
- this->CTest->StartXML(covSumFile, this->AppendXML);
+ this->CTest->StartXML(covSumXML, this->AppendXML);
// Produce output xml files
- covSumFile << "" << std::endl
- << "\t" << coverage_start_time << ""
- << std::endl
- << "\t" << coverage_start_time_time << ""
- << std::endl;
+ covSumXML.StartElement("Coverage");
+ covSumXML.Element("StartDateTime", coverage_start_time);
+ covSumXML.Element("StartTime", coverage_start_time_time);
int logFileCount = 0;
if ( !this->StartCoverageLogFile(covLogFile, logFileCount) )
{
return -1;
}
+ this->StartCoverageLogXML(covLogXML);
cmCTestCoverageHandlerContainer::TotalCoverageMap::iterator fileIterator;
int cnt = 0;
long total_tested = 0;
@@ -528,12 +535,14 @@ int cmCTestCoverageHandler::ProcessHandler()
if ( ++cnt % 100 == 0 )
{
+ this->EndCoverageLogXML(covLogXML);
this->EndCoverageLogFile(covLogFile, logFileCount);
logFileCount ++;
if ( !this->StartCoverageLogFile(covLogFile, logFileCount) )
{
return -1;
}
+ this->StartCoverageLogXML(covLogXML);
}
const std::string fileName
@@ -542,9 +551,10 @@ int cmCTestCoverageHandler::ProcessHandler()
this->CTest->GetShortPathToFile(fullFileName.c_str());
const cmCTestCoverageHandlerContainer::SingleFileCoverageVector& fcov
= fileIterator->second;
- covLogFile << "\t\n"
- << "\t\t" << std::endl;
+ covLogXML.StartElement("File");
+ covLogXML.Attribute("Name", fileName);
+ covLogXML.Attribute("FullPath", shortFileName);
+ covLogXML.StartElement("Report");
cmsys::ifstream ifs(fullFileName.c_str());
if ( !ifs)
@@ -576,9 +586,11 @@ int cmCTestCoverageHandler::ProcessHandler()
error ++;
break;
}
- covLogFile << "\t\t"
- << cmXMLSafe(line) << "" << std::endl;
+ covLogXML.StartElement("Line");
+ covLogXML.Attribute("Number", cc);
+ covLogXML.Attribute("Count", fcov[cc]);
+ covLogXML.Content(line);
+ covLogXML.EndElement(); // Line
if ( fcov[cc] == 0 )
{
untested ++;
@@ -605,24 +617,19 @@ int cmCTestCoverageHandler::ProcessHandler()
}
total_tested += tested;
total_untested += untested;
- covLogFile << "\t\t" << std::endl
- << "\t" << std::endl;
- covSumFile << "\tCTest->GetShortPathToFile(fullFileName.c_str()))
- << "\" Covered=\"" << (tested+untested > 0 ? "true":"false") << "\">\n"
- << "\t\t" << tested << "\n"
- << "\t\t" << untested << "\n"
- << "\t\t";
- covSumFile.setf(std::ios::fixed, std::ios::floatfield);
- covSumFile.precision(2);
- covSumFile << (cper) << "\n"
- << "\t\t";
- covSumFile.setf(std::ios::fixed, std::ios::floatfield);
- covSumFile.precision(2);
- covSumFile << (cmet) << "\n";
- this->WriteXMLLabels(covSumFile, shortFileName);
- covSumFile << "\t" << std::endl;
+ covLogXML.EndElement(); // Report
+ covLogXML.EndElement(); // File
+ covSumXML.StartElement("File");
+ covSumXML.Attribute("Name", fileName);
+ covSumXML.Attribute("FullPath",
+ this->CTest->GetShortPathToFile(fullFileName.c_str()));
+ covSumXML.Attribute("Covered", tested + untested > 0 ? "true" : "false");
+ covSumXML.Element("LOCTested", tested);
+ covSumXML.Element("LOCUnTested", untested);
+ covSumXML.Element("PercentCoverage", cper);
+ covSumXML.Element("CoverageMetric", cmet);
+ this->WriteXMLLabels(covSumXML, shortFileName);
+ covSumXML.EndElement(); // File
}
//Handle all the files in the extra coverage globs that have no cov data
@@ -632,9 +639,10 @@ int cmCTestCoverageHandler::ProcessHandler()
std::string fileName = cmSystemTools::GetFilenameName(*i);
std::string fullPath = cont.SourceDir + "/" + *i;
- covLogFile << "\t\n"
- << "\t\t" << std::endl;
+ covLogXML.StartElement("File");
+ covLogXML.Attribute("Name", fileName);
+ covLogXML.Attribute("FullPath", *i);
+ covLogXML.StartElement("Report");
cmsys::ifstream ifs(fullPath.c_str());
if (!ifs)
@@ -651,24 +659,30 @@ int cmCTestCoverageHandler::ProcessHandler()
"Actually performing coverage for: " << *i << std::endl, this->Quiet);
while (cmSystemTools::GetLineFromStream(ifs, line))
{
- covLogFile << "\t\t"
- << cmXMLSafe(line) << "" << std::endl;
+ covLogXML.StartElement("Line");
+ covLogXML.Attribute("Number", untested);
+ covLogXML.Attribute("Count", 0);
+ covLogXML.Content(line);
+ covLogXML.EndElement(); // Line
untested ++;
}
- covLogFile << "\t\t\n\t" << std::endl;
+ covLogXML.EndElement(); // Report
+ covLogXML.EndElement(); // File
total_untested += untested;
- covSumFile << "\tc_str())
- << "\" Covered=\"true\">\n"
- << "\t\t0\n"
- << "\t\t" << untested << "\n"
- << "\t\t0\n"
- << "\t\t0\n";
- this->WriteXMLLabels(covSumFile, *i);
- covSumFile << "\t" << std::endl;
+ covSumXML.StartElement("File");
+ covSumXML.Attribute("Name", fileName);
+ covSumXML.Attribute("FullPath", *i);
+ covSumXML.Attribute("Covered", "true");
+ covSumXML.Element("LOCTested", 0);
+ covSumXML.Element("LOCUnTested", untested);
+ covSumXML.Element("PercentCoverage", 0);
+ covSumXML.Element("CoverageMetric", 0);
+ this->WriteXMLLabels(covSumXML, *i);
+ covSumXML.EndElement(); // File
}
+ this->EndCoverageLogXML(covLogXML);
this->EndCoverageLogFile(covLogFile, logFileCount);
if (!errorsWhileAccumulating.empty())
@@ -696,22 +710,17 @@ int cmCTestCoverageHandler::ProcessHandler()
std::string end_time = this->CTest->CurrentTime();
- covSumFile << "\t" << total_tested << "\n"
- << "\t" << total_untested << "\n"
- << "\t" << total_lines << "\n"
- << "\t";
- covSumFile.setf(std::ios::fixed, std::ios::floatfield);
- covSumFile.precision(2);
- covSumFile << (percent_coverage)<< "\n"
- << "\t" << end_time << "\n"
- << "\t" <<
- static_cast(cmSystemTools::GetTime())
- << "\n";
- covSumFile << "" <<
- static_cast((cmSystemTools::GetTime() - elapsed_time_start)/6)/10.0
- << ""
- << "" << std::endl;
- this->CTest->EndXML(covSumFile);
+ covSumXML.Element("LOCTested", total_tested);
+ covSumXML.Element("LOCUntested", total_untested);
+ covSumXML.Element("LOC", total_lines);
+ covSumXML.Element("PercentCoverage", percent_coverage);
+ covSumXML.Element("EndDateTime", end_time);
+ covSumXML.Element("EndTime",
+ static_cast(cmSystemTools::GetTime()));
+ covSumXML.Element("ElapsedMinutes",
+ static_cast((cmSystemTools::GetTime() - elapsed_time_start)/6)/10.0);
+ covSumXML.EndElement(); // Coverage
+ this->CTest->EndXML(covSumXML);
cmCTestLog(this->CTest, HANDLER_OUTPUT, "" << std::endl
<< "\tCovered LOC: "
@@ -1952,11 +1961,13 @@ int cmCTestCoverageHandler::RunBullseyeCoverageBranch(
}
// create the output stream for the CoverageLog-N.xml file
cmGeneratedFileStream covLogFile;
+ cmXMLWriter covLogXML(covLogFile);
int logFileCount = 0;
if ( !this->StartCoverageLogFile(covLogFile, logFileCount) )
{
return -1;
}
+ this->StartCoverageLogXML(covLogXML);
// for each file run covbr on that file to get the coverage
// information for that file
std::string outputFile;
@@ -2009,20 +2020,22 @@ int cmCTestCoverageHandler::RunBullseyeCoverageBranch(
// if we are in a valid file close it because a new one started
if(valid)
{
- covLogFile << "\t\t" << std::endl
- << "\t" << std::endl;
+ covLogXML.EndElement(); // Report
+ covLogXML.EndElement(); // File
}
// only allow 100 files in each log file
if ( count != 0 && count % 100 == 0 )
{
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"start a new log file: " << count << std::endl, this->Quiet);
+ this->EndCoverageLogXML(covLogXML);
this->EndCoverageLogFile(covLogFile, logFileCount);
logFileCount ++;
if ( !this->StartCoverageLogFile(covLogFile, logFileCount) )
{
return -1;
}
+ this->StartCoverageLogXML(covLogXML);
count++; // move on one
}
std::map::iterator
@@ -2036,19 +2049,20 @@ int cmCTestCoverageHandler::RunBullseyeCoverageBranch(
"Produce coverage for file: " << file << " " << count
<< std::endl, this->Quiet);
// start the file output
- covLogFile << "\tfirst)
- << "\" FullPath=\"" << cmXMLSafe(
- this->CTest->GetShortPathToFile(
- i->second.c_str())) << "\">" << std::endl
- << "\t\t" << std::endl;
+ covLogXML.StartElement("File");
+ covLogXML.Attribute("Name", i->first);
+ covLogXML.Attribute("FullPath",
+ this->CTest->GetShortPathToFile(i->second.c_str()));
+ covLogXML.StartElement("Report");
// write the bullseye header
line =0;
for(int k =0; bullseyeHelp[k] != 0; ++k)
{
- covLogFile << "\t\t"
- << cmXMLSafe(bullseyeHelp[k])
- << "" << std::endl;
+ covLogXML.StartElement("Line");
+ covLogXML.Attribute("Number", line);
+ covLogXML.Attribute("Count", -1);
+ covLogXML.Content(bullseyeHelp[k]);
+ covLogXML.EndElement(); // Line
line++;
}
valid = true; // we are in a valid file section
@@ -2062,18 +2076,21 @@ int cmCTestCoverageHandler::RunBullseyeCoverageBranch(
// we are not at a start file, and we are in a valid file output the line
else if(valid)
{
- covLogFile << "\t\t"
- << cmXMLSafe(lineIn)
- << "" << std::endl;
+ covLogXML.StartElement("Line");
+ covLogXML.Attribute("Number", line);
+ covLogXML.Attribute("Count", -1);
+ covLogXML.Content(lineIn);
+ covLogXML.EndElement(); // Line
line++;
}
}
// if we ran out of lines a valid file then close that file
if(valid)
{
- covLogFile << "\t\t" << std::endl
- << "\t" << std::endl;
+ covLogXML.EndElement(); // Report
+ covLogXML.EndElement(); // File
}
+ this->EndCoverageLogXML(covLogXML);
this->EndCoverageLogFile(covLogFile, logFileCount);
return 1;
}
@@ -2143,23 +2160,20 @@ int cmCTestCoverageHandler::RunBullseyeSourceSummary(
std::ostream& tmpLog = *cont->OFS;
// copen the Coverage.xml file in the Testing directory
cmGeneratedFileStream covSumFile;
+ cmXMLWriter xml(covSumFile);
if(!this->StartResultingXML(cmCTest::PartCoverage, "Coverage", covSumFile))
{
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Cannot open coverage summary file." << std::endl);
return 0;
}
- this->CTest->StartXML(covSumFile, this->AppendXML);
+ this->CTest->StartXML(xml, this->AppendXML);
double elapsed_time_start = cmSystemTools::GetTime();
std::string coverage_start_time = this->CTest->CurrentTime();
- covSumFile << "" << std::endl
- << "\t"
- << coverage_start_time << ""
- << std::endl
- << "\t"
- << static_cast(cmSystemTools::GetTime())
- << ""
- << std::endl;
+ xml.StartElement("Coverage");
+ xml.Element("StartDateTime", coverage_start_time);
+ xml.Element("StartTime",
+ static_cast(cmSystemTools::GetTime()));
std::string stdline;
std::string errline;
// expected output:
@@ -2271,58 +2285,35 @@ int cmCTestCoverageHandler::RunBullseyeSourceSummary(
tmpLog << "percentBranch: " << percentBranch << "\n";
tmpLog << "percentCoverage: " << percent_coverage << "\n";
tmpLog << "coverage metric: " << cmet << "\n";
- covSumFile << "\t0?"true":"false") << "\">\n"
- << "\t\t"
- << branchCovered
- << "\n"
- << "\t\t"
- << totalBranches - branchCovered
- << "\n"
- << "\t\t"
- << functionsCalled
- << "\n"
- << "\t\t"
- << totalFunctions - functionsCalled
- << "\n"
- // Hack for conversion of function to loc assume a function
- // has 100 lines of code
- << "\t\t" << functionsCalled *100
- << "\n"
- << "\t\t"
- << (totalFunctions - functionsCalled)*100
- << "\n"
- << "\t\t";
- covSumFile.setf(std::ios::fixed, std::ios::floatfield);
- covSumFile.precision(2);
- covSumFile << (cper) << "\n"
- << "\t\t";
- covSumFile.setf(std::ios::fixed, std::ios::floatfield);
- covSumFile.precision(2);
- covSumFile << (cmet) << "\n";
- this->WriteXMLLabels(covSumFile, shortFileName);
- covSumFile << "\t" << std::endl;
+ xml.StartElement("File");
+ xml.Attribute("Name", sourceFile);
+ xml.Attribute("FullPath", shortFileName);
+ xml.Attribute("Covered", cmet > 0 ? "true" : "false");
+ xml.Element("BranchesTested", branchCovered);
+ xml.Element("BranchesUnTested", totalBranches - branchCovered);
+ xml.Element("FunctionsTested", functionsCalled);
+ xml.Element("FunctionsUnTested", totalFunctions - functionsCalled);
+ // Hack for conversion of function to loc assume a function
+ // has 100 lines of code
+ xml.Element("LOCTested", functionsCalled * 100);
+ xml.Element("LOCUnTested", (totalFunctions - functionsCalled) * 100);
+ xml.Element("PercentCoverage", cper);
+ xml.Element("CoverageMetric", cmet);
+ this->WriteXMLLabels(xml, shortFileName);
+ xml.EndElement(); // File
}
}
std::string end_time = this->CTest->CurrentTime();
- covSumFile << "\t" << total_tested << "\n"
- << "\t" << total_untested << "\n"
- << "\t" << total_functions << "\n"
- << "\t";
- covSumFile.setf(std::ios::fixed, std::ios::floatfield);
- covSumFile.precision(2);
- covSumFile
- << SAFEDIV(percent_coverage,number_files)<< "\n"
- << "\t" << end_time << "\n"
- << "\t" << static_cast(cmSystemTools::GetTime())
- << "\n";
- covSumFile
- << "" <<
- static_cast((cmSystemTools::GetTime() - elapsed_time_start)/6)/10.0
- << ""
- << "" << std::endl;
- this->CTest->EndXML(covSumFile);
+ xml.Element("LOCTested", total_tested);
+ xml.Element("LOCUntested", total_untested);
+ xml.Element("LOC", total_functions);
+ xml.Element("PercentCoverage", SAFEDIV(percent_coverage, number_files));
+ xml.Element("EndDateTime", end_time);
+ xml.Element("EndTime", static_cast(cmSystemTools::GetTime()));
+ xml.Element("ElapsedMinutes",
+ static_cast((cmSystemTools::GetTime() - elapsed_time_start)/6)/10.0);
+ xml.EndElement(); // Coverage
+ this->CTest->EndXML(xml);
// Now create the coverage information for each file
return this->RunBullseyeCoverageBranch(cont,
@@ -2514,19 +2505,19 @@ void cmCTestCoverageHandler::LoadLabels(const char* dir)
}
//----------------------------------------------------------------------
-void cmCTestCoverageHandler::WriteXMLLabels(std::ostream& os,
+void cmCTestCoverageHandler::WriteXMLLabels(cmXMLWriter& xml,
std::string const& source)
{
LabelMapType::const_iterator li = this->SourceLabels.find(source);
if(li != this->SourceLabels.end() && !li->second.empty())
{
- os << "\t\t\n";
+ xml.StartElement("Labels");
for(LabelSet::const_iterator lsi = li->second.begin();
lsi != li->second.end(); ++lsi)
{
- os << "\t\t\t\n";
+ xml.Element("Label", this->Labels[*lsi]);
}
- os << "\t\t\n";
+ xml.EndElement(); // Labels
}
}
diff --git a/Source/CTest/cmCTestCoverageHandler.h b/Source/CTest/cmCTestCoverageHandler.h
index 3258ddbe6..2ca123a20 100644
--- a/Source/CTest/cmCTestCoverageHandler.h
+++ b/Source/CTest/cmCTestCoverageHandler.h
@@ -20,6 +20,7 @@
#include
class cmGeneratedFileStream;
+class cmXMLWriter;
class cmCTestCoverageHandlerContainer
{
public:
@@ -65,6 +66,9 @@ private:
bool StartCoverageLogFile(cmGeneratedFileStream& ostr, int logFileCount);
void EndCoverageLogFile(cmGeneratedFileStream& ostr, int logFileCount);
+ void StartCoverageLogXML(cmXMLWriter& xml);
+ void EndCoverageLogXML(cmXMLWriter& xml);
+
//! Handle coverage using GCC's GCov
int HandleGCovCoverage(cmCTestCoverageHandlerContainer* cont);
void FindGCovFiles(std::vector& files);
@@ -146,7 +150,7 @@ private:
// Label reading and writing methods.
void LoadLabels();
void LoadLabels(const char* dir);
- void WriteXMLLabels(std::ostream& os, std::string const& source);
+ void WriteXMLLabels(cmXMLWriter& xml, std::string const& source);
// Label-based filtering.
std::set LabelFilter;
diff --git a/Source/CTest/cmCTestGlobalVC.cxx b/Source/CTest/cmCTestGlobalVC.cxx
index 5f570b5d3..c091ec47e 100644
--- a/Source/CTest/cmCTestGlobalVC.cxx
+++ b/Source/CTest/cmCTestGlobalVC.cxx
@@ -13,7 +13,7 @@
#include "cmCTest.h"
#include "cmSystemTools.h"
-#include "cmXMLSafe.h"
+#include "cmXMLWriter.h"
#include
@@ -91,36 +91,36 @@ void cmCTestGlobalVC::DoModification(PathStatus status,
}
//----------------------------------------------------------------------------
-void cmCTestGlobalVC::WriteXMLDirectory(std::ostream& xml,
+void cmCTestGlobalVC::WriteXMLDirectory(cmXMLWriter& xml,
std::string const& path,
Directory const& dir)
{
const char* slash = path.empty()? "":"/";
- xml << "\t\n"
- << "\t\t" << cmXMLSafe(path) << "\n";
+ xml.StartElement("Directory");
+ xml.Element("Name", path);
for(Directory::const_iterator fi = dir.begin(); fi != dir.end(); ++fi)
{
std::string full = path + slash + fi->first;
this->WriteXMLEntry(xml, path, fi->first, full, fi->second);
}
- xml << "\t\n";
+ xml.EndElement(); // Directory
}
//----------------------------------------------------------------------------
-void cmCTestGlobalVC::WriteXMLGlobal(std::ostream& xml)
+void cmCTestGlobalVC::WriteXMLGlobal(cmXMLWriter& xml)
{
if(!this->NewRevision.empty())
{
- xml << "\t" << this->NewRevision << "\n";
+ xml.Element("Revision", this->NewRevision);
}
if(!this->OldRevision.empty() && this->OldRevision != this->NewRevision)
{
- xml << "\t" << this->OldRevision << "\n";
+ xml.Element("PriorRevision", this->OldRevision);
}
}
//----------------------------------------------------------------------------
-bool cmCTestGlobalVC::WriteXMLUpdates(std::ostream& xml)
+bool cmCTestGlobalVC::WriteXMLUpdates(cmXMLWriter& xml)
{
cmCTestLog(this->CTest, HANDLER_OUTPUT,
" Gathering version information (one . per revision):\n"
diff --git a/Source/CTest/cmCTestGlobalVC.h b/Source/CTest/cmCTestGlobalVC.h
index 29e0a61ec..d0e94109c 100644
--- a/Source/CTest/cmCTestGlobalVC.h
+++ b/Source/CTest/cmCTestGlobalVC.h
@@ -30,7 +30,7 @@ public:
protected:
// Implement cmCTestVC internal API.
- virtual bool WriteXMLUpdates(std::ostream& xml);
+ virtual bool WriteXMLUpdates(cmXMLWriter& xml);
/** Represent a vcs-reported action for one path in a revision. */
struct Change
@@ -62,8 +62,8 @@ protected:
virtual void LoadModifications() = 0;
virtual void LoadRevisions() = 0;
- virtual void WriteXMLGlobal(std::ostream& xml);
- void WriteXMLDirectory(std::ostream& xml, std::string const& path,
+ virtual void WriteXMLGlobal(cmXMLWriter& xml);
+ void WriteXMLDirectory(cmXMLWriter& xml, std::string const& path,
Directory const& dir);
};
diff --git a/Source/CTest/cmCTestLaunch.cxx b/Source/CTest/cmCTestLaunch.cxx
index a8a4a1e1b..0f588c584 100644
--- a/Source/CTest/cmCTestLaunch.cxx
+++ b/Source/CTest/cmCTestLaunch.cxx
@@ -13,7 +13,7 @@
#include "cmGeneratedFileStream.h"
#include "cmSystemTools.h"
-#include "cmXMLSafe.h"
+#include "cmXMLWriter.h"
#include "cmake.h"
#include
@@ -407,35 +407,32 @@ void cmCTestLaunch::WriteXML()
// Use cmGeneratedFileStream to atomically create the report file.
cmGeneratedFileStream fxml(logXML.c_str());
- fxml << "\tIsError()? "Error" : "Warning") << "\">\n";
- this->WriteXMLAction(fxml);
- this->WriteXMLCommand(fxml);
- this->WriteXMLResult(fxml);
- this->WriteXMLLabels(fxml);
- fxml << "\t\n";
+ cmXMLWriter xml(fxml, 2);
+ xml.StartElement("Failure");
+ xml.Attribute("type", this->IsError() ? "Error" : "Warning");
+ this->WriteXMLAction(xml);
+ this->WriteXMLCommand(xml);
+ this->WriteXMLResult(xml);
+ this->WriteXMLLabels(xml);
+ xml.EndElement(); // Failure
}
//----------------------------------------------------------------------------
-void cmCTestLaunch::WriteXMLAction(std::ostream& fxml)
+void cmCTestLaunch::WriteXMLAction(cmXMLWriter& xml)
{
- fxml << "\t\t\n";
- fxml << "\t\t\n";
+ xml.Comment("Meta-information about the build action");
+ xml.StartElement("Action");
// TargetName
if(!this->OptionTargetName.empty())
{
- fxml << "\t\t\t"
- << cmXMLSafe(this->OptionTargetName)
- << "\n";
+ xml.Element("TargetName", this->OptionTargetName);
}
// Language
if(!this->OptionLanguage.empty())
{
- fxml << "\t\t\t"
- << cmXMLSafe(this->OptionLanguage)
- << "\n";
+ xml.Element("Language", this->OptionLanguage);
}
// SourceFile
@@ -454,17 +451,13 @@ void cmCTestLaunch::WriteXMLAction(std::ostream& fxml)
source.c_str());
}
- fxml << "\t\t\t"
- << cmXMLSafe(source)
- << "\n";
+ xml.Element("SourceFile", source);
}
// OutputFile
if(!this->OptionOutput.empty())
{
- fxml << "\t\t\t"
- << cmXMLSafe(this->OptionOutput)
- << "\n";
+ xml.Element("OutputFile", this->OptionOutput);
}
// OutputType
@@ -494,103 +487,94 @@ void cmCTestLaunch::WriteXMLAction(std::ostream& fxml)
}
if(outputType)
{
- fxml << "\t\t\t"
- << cmXMLSafe(outputType)
- << "\n";
+ xml.Element("OutputType", outputType);
}
- fxml << "\t\t\n";
+ xml.EndElement(); // Action
}
//----------------------------------------------------------------------------
-void cmCTestLaunch::WriteXMLCommand(std::ostream& fxml)
+void cmCTestLaunch::WriteXMLCommand(cmXMLWriter& xml)
{
- fxml << "\n";
- fxml << "\t\t\n";
- fxml << "\t\t\n";
+ xml.Comment("Details of command");
+ xml.StartElement("Command");
if(!this->CWD.empty())
{
- fxml << "\t\t\t"
- << cmXMLSafe(this->CWD)
- << "\n";
+ xml.Element("WorkingDirectory", this->CWD);
}
for(std::vector::const_iterator ai = this->RealArgs.begin();
ai != this->RealArgs.end(); ++ai)
{
- fxml << "\t\t\t"
- << cmXMLSafe(ai->c_str())
- << "\n";
+ xml.Element("Argument", *ai);
}
- fxml << "\t\t\n";
+ xml.EndElement(); // Command
}
//----------------------------------------------------------------------------
-void cmCTestLaunch::WriteXMLResult(std::ostream& fxml)
+void cmCTestLaunch::WriteXMLResult(cmXMLWriter& xml)
{
- fxml << "\n";
- fxml << "\t\t\n";
- fxml << "\t\t\n";
+ xml.Comment("Result of command");
+ xml.StartElement("Result");
// StdOut
- fxml << "\t\t\t";
- this->DumpFileToXML(fxml, this->LogOut);
- fxml << "\n";
+ xml.StartElement("StdOut");
+ this->DumpFileToXML(xml, this->LogOut);
+ xml.EndElement(); // StdOut
// StdErr
- fxml << "\t\t\t";
- this->DumpFileToXML(fxml, this->LogErr);
- fxml << "\n";
+ xml.StartElement("StdErr");
+ this->DumpFileToXML(xml, this->LogErr);
+ xml.EndElement(); // StdErr
// ExitCondition
- fxml << "\t\t\t";
+ xml.StartElement("ExitCondition");
cmsysProcess* cp = this->Process;
switch (cmsysProcess_GetState(cp))
{
case cmsysProcess_State_Starting:
- fxml << "No process has been executed"; break;
+ xml.Content("No process has been executed"); break;
case cmsysProcess_State_Executing:
- fxml << "The process is still executing"; break;
+ xml.Content("The process is still executing"); break;
case cmsysProcess_State_Disowned:
- fxml << "Disowned"; break;
+ xml.Content("Disowned"); break;
case cmsysProcess_State_Killed:
- fxml << "Killed by parent"; break;
+ xml.Content("Killed by parent"); break;
case cmsysProcess_State_Expired:
- fxml << "Killed when timeout expired"; break;
+ xml.Content("Killed when timeout expired"); break;
case cmsysProcess_State_Exited:
- fxml << this->ExitCode; break;
+ xml.Content(this->ExitCode); break;
case cmsysProcess_State_Exception:
- fxml << "Terminated abnormally: "
- << cmXMLSafe(cmsysProcess_GetExceptionString(cp)); break;
+ xml.Content("Terminated abnormally: ");
+ xml.Content(cmsysProcess_GetExceptionString(cp)); break;
case cmsysProcess_State_Error:
- fxml << "Error administrating child process: "
- << cmXMLSafe(cmsysProcess_GetErrorString(cp)); break;
+ xml.Content("Error administrating child process: ");
+ xml.Content(cmsysProcess_GetErrorString(cp)); break;
};
- fxml << "\n";
+ xml.EndElement(); // ExitCondition
- fxml << "\t\t\n";
+ xml.EndElement(); // Result
}
//----------------------------------------------------------------------------
-void cmCTestLaunch::WriteXMLLabels(std::ostream& fxml)
+void cmCTestLaunch::WriteXMLLabels(cmXMLWriter& xml)
{
this->LoadLabels();
if(!this->Labels.empty())
{
- fxml << "\n";
- fxml << "\t\t\n";
- fxml << "\t\t\n";
+ xml.Comment("Interested parties");
+ xml.StartElement("Labels");
for(std::set::const_iterator li = this->Labels.begin();
li != this->Labels.end(); ++li)
{
- fxml << "\t\t\t\n";
+ xml.Element("Label", *li);
}
- fxml << "\t\t\n";
+ xml.EndElement(); // Labels
}
}
//----------------------------------------------------------------------------
-void cmCTestLaunch::DumpFileToXML(std::ostream& fxml,
+void cmCTestLaunch::DumpFileToXML(cmXMLWriter& xml,
std::string const& fname)
{
cmsys::ifstream fin(fname.c_str(), std::ios::in | std::ios::binary);
@@ -605,7 +589,8 @@ void cmCTestLaunch::DumpFileToXML(std::ostream& fxml,
continue;
}
- fxml << sep << cmXMLSafe(line).Quotes(false);
+ xml.Content(sep);
+ xml.Content(line);
sep = "\n";
}
}
diff --git a/Source/CTest/cmCTestLaunch.h b/Source/CTest/cmCTestLaunch.h
index bc90d28cf..b13e4847b 100644
--- a/Source/CTest/cmCTestLaunch.h
+++ b/Source/CTest/cmCTestLaunch.h
@@ -15,6 +15,8 @@
#include "cmStandardIncludes.h"
#include
+class cmXMLWriter;
+
/** \class cmCTestLaunch
* \brief Launcher for make rules to report results for ctest
*
@@ -92,11 +94,11 @@ private:
// Methods to generate the xml fragment.
void WriteXML();
- void WriteXMLAction(std::ostream& fxml);
- void WriteXMLCommand(std::ostream& fxml);
- void WriteXMLResult(std::ostream& fxml);
- void WriteXMLLabels(std::ostream& fxml);
- void DumpFileToXML(std::ostream& fxml, std::string const& fname);
+ void WriteXMLAction(cmXMLWriter& xml);
+ void WriteXMLCommand(cmXMLWriter& xml);
+ void WriteXMLResult(cmXMLWriter& xml);
+ void WriteXMLLabels(cmXMLWriter& xml);
+ void DumpFileToXML(cmXMLWriter& xml, std::string const& fname);
// Configuration
void LoadConfig();
diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx
index 061f3fd6b..8f267163d 100644
--- a/Source/CTest/cmCTestMemCheckHandler.cxx
+++ b/Source/CTest/cmCTestMemCheckHandler.cxx
@@ -21,7 +21,7 @@
#include
#include
#include "cmMakefile.h"
-#include "cmXMLSafe.h"
+#include "cmXMLWriter.h"
#include
#include
@@ -352,55 +352,52 @@ void cmCTestMemCheckHandler::PopulateCustomVectors(cmMakefile *mf)
}
//----------------------------------------------------------------------
-void cmCTestMemCheckHandler::GenerateDartOutput(std::ostream& os)
+void cmCTestMemCheckHandler::GenerateDartOutput(cmXMLWriter& xml)
{
if ( !this->CTest->GetProduceXML() )
{
return;
}
- this->CTest->StartXML(os, this->AppendXML);
- os << "CTest->StartXML(xml, this->AppendXML);
+ xml.StartElement("DynamicAnalysis");
switch ( this->MemoryTesterStyle )
{
case cmCTestMemCheckHandler::VALGRIND:
- os << "Valgrind";
+ xml.Attribute("Checker", "Valgrind");
break;
case cmCTestMemCheckHandler::PURIFY:
- os << "Purify";
+ xml.Attribute("Checker", "Purify");
break;
case cmCTestMemCheckHandler::BOUNDS_CHECKER:
- os << "BoundsChecker";
+ xml.Attribute("Checker", "BoundsChecker");
break;
case cmCTestMemCheckHandler::ADDRESS_SANITIZER:
- os << "AddressSanitizer";
+ xml.Attribute("Checker", "AddressSanitizer");
break;
case cmCTestMemCheckHandler::THREAD_SANITIZER:
- os << "ThreadSanitizer";
+ xml.Attribute("Checker", "ThreadSanitizer");
break;
case cmCTestMemCheckHandler::MEMORY_SANITIZER:
- os << "MemorySanitizer";
+ xml.Attribute("Checker", "MemorySanitizer");
break;
case cmCTestMemCheckHandler::UB_SANITIZER:
- os << "UndefinedBehaviorSanitizer";
+ xml.Attribute("Checker", "UndefinedBehaviorSanitizer");
break;
default:
- os << "Unknown";
+ xml.Attribute("Checker", "Unknown");
}
- os << "\">" << std::endl;
- os << "\t" << this->StartTest << "\n"
- << "\t" << this->StartTestTime << "\n"
- << "\t\n";
+ xml.Element("StartDateTime", this->StartTest);
+ xml.Element("StartTestTime", this->StartTestTime);
+ xml.StartElement("TestList");
cmCTestMemCheckHandler::TestResultsVector::size_type cc;
for ( cc = 0; cc < this->TestResults.size(); cc ++ )
{
cmCTestTestResult *result = &this->TestResults[cc];
std::string testPath = result->Path + "/" + result->Name;
- os << "\t\t" << cmXMLSafe(
- this->CTest->GetShortPathToFile(testPath.c_str()))
- << "" << std::endl;
+ xml.Element("Test", this->CTest->GetShortPathToFile(testPath.c_str()));
}
- os << "\t\n";
+ xml.EndElement(); // TestList
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
"-- Processing memory checking output: ", this->Quiet);
size_t total = this->TestResults.size();
@@ -419,37 +416,33 @@ void cmCTestMemCheckHandler::GenerateDartOutput(std::ostream& os)
}
this->CleanTestOutput(memcheckstr,
static_cast(this->CustomMaximumFailedTestOutputSize));
- this->WriteTestResultHeader(os, result);
- os << "\t\t" << std::endl;
+ this->WriteTestResultHeader(xml, result);
+ xml.StartElement("Results");
for(std::vector::size_type kk = 0;
kk < memcheckresults.size(); ++kk)
{
if ( memcheckresults[kk] )
{
- os << "\t\t\tResultStringsLong[kk]
- << "\">"
- << memcheckresults[kk]
- << "" << std::endl;
+ xml.StartElement("Defect");
+ xml.Attribute("type", this->ResultStringsLong[kk]);
+ xml.Content(memcheckresults[kk]);
+ xml.EndElement(); // Defect
}
this->GlobalResults[kk] += memcheckresults[kk];
}
+ xml.EndElement(); // Results
- std::string logTag;
+ xml.StartElement("Log");
if(this->CTest->ShouldCompressMemCheckOutput())
{
this->CTest->CompressString(memcheckstr);
- logTag = "\t\n";
- }
- else
- {
- logTag = "\t\n";
+ xml.Attribute("compression", "gzip");
+ xml.Attribute("encoding", "base64");
}
+ xml.Content(memcheckstr);
+ xml.EndElement(); // Log
- os
- << "\t\t\n"
- << logTag << cmXMLSafe(memcheckstr) << std::endl
- << "\t\n";
- this->WriteTestResultFooter(os, result);
+ this->WriteTestResultFooter(xml, result);
if ( current < cc )
{
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "#" << std::flush,
@@ -460,7 +453,7 @@ void cmCTestMemCheckHandler::GenerateDartOutput(std::ostream& os)
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, std::endl, this->Quiet);
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "Memory checking results:"
<< std::endl, this->Quiet);
- os << "\t" << std::endl;
+ xml.StartElement("DefectList");
for ( cc = 0; cc < this->GlobalResults.size(); cc ++ )
{
if ( this->GlobalResults[cc] )
@@ -473,21 +466,20 @@ void cmCTestMemCheckHandler::GenerateDartOutput(std::ostream& os)
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
this->ResultStringsLong[cc] << " - "
<< this->GlobalResults[cc] << std::endl, this->Quiet);
- os << "\t\tResultStringsLong[cc]
- << "\"/>" << std::endl;
+ xml.StartElement("Defect");
+ xml.Attribute("Type", this->ResultStringsLong[cc]);
+ xml.EndElement();
}
}
- os << "\t" << std::endl;
+ xml.EndElement(); // DefectList
- os << "\t" << this->EndTest << "" << std::endl;
- os << "\t" << this->EndTestTime
- << "" << std::endl;
- os << ""
- << static_cast(this->ElapsedTestingTime/6)/10.0
- << "\n";
+ xml.Element("EndDateTime", this->EndTest);
+ xml.Element("EndTestTime", this->EndTestTime);
+ xml.Element("ElapsedMinutes",
+ static_cast(this->ElapsedTestingTime/6)/10.0);
- os << "" << std::endl;
- this->CTest->EndXML(os);
+ xml.EndElement(); // DynamicAnalysis
+ this->CTest->EndXML(xml);
}
//----------------------------------------------------------------------
diff --git a/Source/CTest/cmCTestMemCheckHandler.h b/Source/CTest/cmCTestMemCheckHandler.h
index 69fdd9f8c..f1ac794dc 100644
--- a/Source/CTest/cmCTestMemCheckHandler.h
+++ b/Source/CTest/cmCTestMemCheckHandler.h
@@ -21,6 +21,7 @@
#include
class cmMakefile;
+class cmXMLWriter;
/** \class cmCTestMemCheckHandler
* \brief A class that handles ctest -S invocations
@@ -119,7 +120,7 @@ private:
/**
* Generate the Dart compatible output
*/
- void GenerateDartOutput(std::ostream& os);
+ void GenerateDartOutput(cmXMLWriter& xml);
std::vector CustomPreMemCheck;
std::vector CustomPostMemCheck;
diff --git a/Source/CTest/cmCTestSVN.cxx b/Source/CTest/cmCTestSVN.cxx
index 86dc2f2fd..f7bd1f941 100644
--- a/Source/CTest/cmCTestSVN.cxx
+++ b/Source/CTest/cmCTestSVN.cxx
@@ -14,7 +14,7 @@
#include "cmCTest.h"
#include "cmSystemTools.h"
#include "cmXMLParser.h"
-#include "cmXMLSafe.h"
+#include "cmXMLWriter.h"
#include
@@ -535,11 +535,11 @@ void cmCTestSVN::LoadModifications()
}
//----------------------------------------------------------------------------
-void cmCTestSVN::WriteXMLGlobal(std::ostream& xml)
+void cmCTestSVN::WriteXMLGlobal(cmXMLWriter& xml)
{
this->cmCTestGlobalVC::WriteXMLGlobal(xml);
- xml << "\t" << this->RootInfo->Base << "\n";
+ xml.Element("SVNPath", this->RootInfo->Base);
}
//----------------------------------------------------------------------------
diff --git a/Source/CTest/cmCTestSVN.h b/Source/CTest/cmCTestSVN.h
index 17bf7cb6f..f9febc52b 100644
--- a/Source/CTest/cmCTestSVN.h
+++ b/Source/CTest/cmCTestSVN.h
@@ -84,7 +84,7 @@ private:
void DoRevisionSVN(Revision const& revision,
std::vector const& changes);
- void WriteXMLGlobal(std::ostream& xml);
+ void WriteXMLGlobal(cmXMLWriter& xml);
// Parsing helper classes.
class InfoParser;
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index 7eb8392de..70b7f5cb5 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -27,7 +27,7 @@
#include "cmLocalGenerator.h"
#include "cmCommand.h"
#include "cmSystemTools.h"
-#include "cmXMLSafe.h"
+#include "cmXMLWriter.h"
#include "cm_utf8.h"
#include
@@ -633,7 +633,8 @@ int cmCTestTestHandler::ProcessHandler()
this->LogFile = 0;
return 1;
}
- this->GenerateDartOutput(xmlfile);
+ cmXMLWriter xml(xmlfile);
+ this->GenerateDartOutput(xml);
}
if ( ! this->PostProcessHandler() )
@@ -1142,54 +1143,53 @@ void cmCTestTestHandler::GenerateTestCommand(std::vector&, int)
}
//----------------------------------------------------------------------
-void cmCTestTestHandler::GenerateDartOutput(std::ostream& os)
+void cmCTestTestHandler::GenerateDartOutput(cmXMLWriter& xml)
{
if ( !this->CTest->GetProduceXML() )
{
return;
}
- this->CTest->StartXML(os, this->AppendXML);
- os << "\n"
- << "\t" << this->StartTest << "\n"
- << "\t" << this->StartTestTime << "\n"
- << "\t\n";
+ this->CTest->StartXML(xml, this->AppendXML);
+ xml.StartElement("Testing");
+ xml.Element("StartDateTime", this->StartTest);
+ xml.Element("StartTestTime", this->StartTestTime);
+ xml.StartElement("TestList");
cmCTestTestHandler::TestResultsVector::size_type cc;
for ( cc = 0; cc < this->TestResults.size(); cc ++ )
{
cmCTestTestResult *result = &this->TestResults[cc];
std::string testPath = result->Path + "/" + result->Name;
- os << "\t\t" << cmXMLSafe(
- this->CTest->GetShortPathToFile(testPath.c_str()))
- << "" << std::endl;
+ xml.Element("Test", this->CTest->GetShortPathToFile(testPath.c_str()));
}
- os << "\t\n";
+ xml.EndElement(); // TestList
for ( cc = 0; cc < this->TestResults.size(); cc ++ )
{
cmCTestTestResult *result = &this->TestResults[cc];
- this->WriteTestResultHeader(os, result);
- os << "\t\t" << std::endl;
+ this->WriteTestResultHeader(xml, result);
+ xml.StartElement("Results");
if ( result->Status != cmCTestTestHandler::NOT_RUN )
{
if ( result->Status != cmCTestTestHandler::COMPLETED ||
result->ReturnValue )
{
- os << "\t\t\t"
- << cmXMLSafe(this->GetTestStatus(result->Status))
- << ""
- "\n"
- << "\t\t\t"
- << result->ReturnValue
- << ""
- << std::endl;
+ xml.StartElement("NamedMeasurement");
+ xml.Attribute("type", "text/string");
+ xml.Attribute("name", "Exit Code");
+ xml.Element("Value", this->GetTestStatus(result->Status));
+ xml.EndElement(); // NamedMeasurement
+ xml.StartElement("NamedMeasurement");
+ xml.Attribute("type", "text/string");
+ xml.Attribute("name", "Exit Value");
+ xml.Element("Value", result->ReturnValue);
+ xml.EndElement(); // NamedMeasurement
}
- this->GenerateRegressionImages(os, result->DartString);
- os << "\t\t\t"
- << result->ExecutionTime
- << "\n";
+ this->GenerateRegressionImages(xml, result->DartString);
+ xml.StartElement("NamedMeasurement");
+ xml.Attribute("type", "numeric/double");
+ xml.Attribute("name", "Execution Time");
+ xml.Element("Value", result->ExecutionTime);
+ xml.EndElement(); // NamedMeasurement
if(!result->Reason.empty())
{
const char* reasonType = "Pass Reason";
@@ -1198,109 +1198,103 @@ void cmCTestTestHandler::GenerateDartOutput(std::ostream& os)
{
reasonType = "Fail Reason";
}
- os << "\t\t\t"
- << cmXMLSafe(result->Reason)
- << "\n";
+ xml.StartElement("NamedMeasurement");
+ xml.Attribute("type", "text/string");
+ xml.Attribute("name", reasonType);
+ xml.Element("Value", result->Reason);
+ xml.EndElement(); // NamedMeasurement
}
- os
- << "\t\t\t"
- << cmXMLSafe(result->CompletionStatus)
- << "\n";
+ xml.StartElement("NamedMeasurement");
+ xml.Attribute("type", "text/string");
+ xml.Attribute("name", "Completion Status");
+ xml.Element("Value", result->CompletionStatus);
+ xml.EndElement(); // NamedMeasurement
}
- os
- << "\t\t\t"
- << cmXMLSafe(result->FullCommandLine)
- << "\n";
+ xml.StartElement("NamedMeasurement");
+ xml.Attribute("type", "text/string");
+ xml.Attribute("name", "Command Line");
+ xml.Element("Value", result->FullCommandLine);
+ xml.EndElement(); // NamedMeasurement
std::map::iterator measureIt;
for ( measureIt = result->Properties->Measurements.begin();
measureIt != result->Properties->Measurements.end();
++ measureIt )
{
- os
- << "\t\t\tfirst << "\">"
- << cmXMLSafe(measureIt->second)
- << "\n";
+ xml.StartElement("NamedMeasurement");
+ xml.Attribute("type", "text/string");
+ xml.Attribute("name", measureIt->first);
+ xml.Element("Value", measureIt->second);
+ xml.EndElement(); // NamedMeasurement
}
- os
- << "\t\t\t\n"
- << "\t\t\t\tCompressOutput ?
- " encoding=\"base64\" compression=\"gzip\">"
- : ">");
- os << cmXMLSafe(result->Output);
- os
- << "\n"
- << "\t\t\t\n"
- << "\t\t\n";
+ xml.StartElement("Measurement");
+ xml.StartElement("Value");
+ if (result->CompressOutput)
+ {
+ xml.Attribute("encoding", "base64");
+ xml.Attribute("compression", "gzip");
+ }
+ xml.Content(result->Output);
+ xml.EndElement(); // Value
+ xml.EndElement(); // Measurement
+ xml.EndElement(); // Results
- this->AttachFiles(os, result);
- this->WriteTestResultFooter(os, result);
+ this->AttachFiles(xml, result);
+ this->WriteTestResultFooter(xml, result);
}
- os << "\t" << this->EndTest << "\n"
- << "\t" << this->EndTestTime << "\n"
- << ""
- << static_cast(this->ElapsedTestingTime/6)/10.0
- << ""
- << "" << std::endl;
- this->CTest->EndXML(os);
+ xml.Element("EndDateTime", this->EndTest);
+ xml.Element("EndTestTime", this->EndTestTime);
+ xml.Element("ElapsedMinutes",
+ static_cast(this->ElapsedTestingTime/6)/10.0);
+ xml.EndElement(); // Testing
+ this->CTest->EndXML(xml);
}
//----------------------------------------------------------------------------
-void cmCTestTestHandler::WriteTestResultHeader(std::ostream& os,
+void cmCTestTestHandler::WriteTestResultHeader(cmXMLWriter& xml,
cmCTestTestResult* result)
{
- os << "\tStatus == cmCTestTestHandler::COMPLETED )
{
- os << "passed";
+ xml.Attribute("Status", "passed");
}
else if ( result->Status == cmCTestTestHandler::NOT_RUN )
{
- os << "notrun";
+ xml.Attribute("Status", "notrun");
}
else
{
- os << "failed";
+ xml.Attribute("Status", "failed");
}
std::string testPath = result->Path + "/" + result->Name;
- os << "\">\n"
- << "\t\t" << cmXMLSafe(result->Name) << "\n"
- << "\t\t" << cmXMLSafe(
- this->CTest->GetShortPathToFile(result->Path.c_str())) << "\n"
- << "\t\t" << cmXMLSafe(
- this->CTest->GetShortPathToFile(testPath.c_str())) << "\n"
- << "\t\t"
- << cmXMLSafe(result->FullCommandLine)
- << "\n";
+ xml.Element("Name", result->Name);
+ xml.Element("Path", this->CTest->GetShortPathToFile(result->Path.c_str()));
+ xml.Element("FullName", this->CTest->GetShortPathToFile(testPath.c_str()));
+ xml.Element("FullCommandLine", result->FullCommandLine);
}
//----------------------------------------------------------------------------
-void cmCTestTestHandler::WriteTestResultFooter(std::ostream& os,
+void cmCTestTestHandler::WriteTestResultFooter(cmXMLWriter& xml,
cmCTestTestResult* result)
{
if(!result->Properties->Labels.empty())
{
- os << "\t\t\n";
+ xml.StartElement("Labels");
std::vector const& labels = result->Properties->Labels;
for(std::vector::const_iterator li = labels.begin();
li != labels.end(); ++li)
{
- os << "\t\t\t\n";
+ xml.Element("Label", *li);
}
- os << "\t\t\n";
+ xml.EndElement(); // Labels
}
- os
- << "\t" << std::endl;
+ xml.EndElement(); // Test
}
//----------------------------------------------------------------------
-void cmCTestTestHandler::AttachFiles(std::ostream& os,
+void cmCTestTestHandler::AttachFiles(cmXMLWriter& xml,
cmCTestTestResult* result)
{
if(result->Status != cmCTestTestHandler::COMPLETED
@@ -1317,11 +1311,14 @@ void cmCTestTestHandler::AttachFiles(std::ostream& os,
{
const std::string &base64 = this->CTest->Base64GzipEncodeFile(*file);
std::string fname = cmSystemTools::GetFilenameName(*file);
- os << "\t\t"
- "\n\t\t\t\n\t\t\t"
- << base64
- << "\n\t\t\t\n\t\t\n";
+ xml.StartElement("NamedMeasurement");
+ xml.Attribute("name", "Attached File");
+ xml.Attribute("encoding", "base64");
+ xml.Attribute("compression", "tar/gzip");
+ xml.Attribute("filename", fname);
+ xml.Attribute("type", "file");
+ xml.Element("Value", base64);
+ xml.EndElement(); // NamedMeasurement
}
}
@@ -1828,7 +1825,7 @@ void cmCTestTestHandler::ExpandTestsToRunInformationForRerunFailed()
#define SPACE_REGEX "[ \t\r\n]"
//----------------------------------------------------------------------
void cmCTestTestHandler::GenerateRegressionImages(
- std::ostream& ostr, const std::string& xml)
+ cmXMLWriter& xml, const std::string& dart)
{
cmsys::RegularExpression twoattributes(
"([^<]*)");
bool done = false;
- std::string cxml = xml;
+ std::string cxml = dart;
while ( ! done )
{
if ( twoattributes.find(cxml) )
{
- ostr
- << "\t\t\t" << twoattributes.match(5)
- << ""
- << std::endl;
+ xml.StartElement("NamedMeasurement");
+ xml.Attribute(twoattributes.match(1).c_str(),
+ twoattributes.match(2));
+ xml.Attribute(twoattributes.match(3).c_str(),
+ twoattributes.match(4));
+ xml.Element("Value", twoattributes.match(5));
+ xml.EndElement();
cxml.erase(twoattributes.start(),
twoattributes.end() - twoattributes.start());
}
else if ( threeattributes.find(cxml) )
{
- ostr
- << "\t\t\t" << threeattributes.match(7)
- << ""
- << std::endl;
+ xml.StartElement("NamedMeasurement");
+ xml.Attribute(threeattributes.match(1).c_str(),
+ threeattributes.match(2));
+ xml.Attribute(threeattributes.match(3).c_str(),
+ threeattributes.match(4));
+ xml.Attribute(threeattributes.match(5).c_str(),
+ threeattributes.match(6));
+ xml.Element("Value", twoattributes.match(7));
+ xml.EndElement();
cxml.erase(threeattributes.start(),
threeattributes.end() - threeattributes.start());
}
else if ( fourattributes.find(cxml) )
{
- ostr
- << "\t\t\t" << fourattributes.match(9)
- << ""
- << std::endl;
+ xml.StartElement("NamedMeasurement");
+ xml.Attribute(fourattributes.match(1).c_str(),
+ fourattributes.match(2));
+ xml.Attribute(fourattributes.match(3).c_str(),
+ fourattributes.match(4));
+ xml.Attribute(fourattributes.match(5).c_str(),
+ fourattributes.match(6));
+ xml.Attribute(fourattributes.match(7).c_str(),
+ fourattributes.match(8));
+ xml.Element("Value", twoattributes.match(9));
+ xml.EndElement();
cxml.erase(fourattributes.start(),
fourattributes.end() - fourattributes.start());
}
else if ( cdatastart.find(cxml) && cdataend.find(cxml) )
{
- ostr
- << "\t\t\t"
- << std::endl;
+ xml.StartElement("NamedMeasurement");
+ xml.Attribute(cdatastart.match(1).c_str(), cdatastart.match(2));
+ xml.Attribute(cdatastart.match(3).c_str(), cdatastart.match(4));
+ xml.StartElement("Value");
+ xml.CData(
+ cxml.substr(cdatastart.end(), cdataend.start() - cdatastart.end()));
+ xml.EndElement(); // Value
+ xml.EndElement(); // NamedMeasurement
cxml.erase(cdatastart.start(),
cdataend.end() - cdatastart.start());
}
@@ -1952,13 +1941,12 @@ void cmCTestTestHandler::GenerateRegressionImages(
v2 = "text/string";
}
- ostr
- << "\t\t\tImage " << filename
- << " is empty";
+ xml.StartElement("NamedMeasurement");
+ xml.Attribute(k1.c_str(), v1);
+ xml.Attribute(k2.c_str(), v2);
+ xml.Attribute("encoding", "none");
+ xml.Element("Value", "Image " + filename + " is empty");
+ xml.EndElement();
}
else
{
@@ -1976,14 +1964,13 @@ void cmCTestTestHandler::GenerateRegressionImages(
size_t rlen
= cmsysBase64_Encode(file_buffer, len, encoded_buffer, 1);
- ostr
- << "\t\t\t" << std::endl << "\t\t\t\t";
+ xml.StartElement("NamedMeasurement");
+ xml.Attribute(measurementfile.match(1).c_str(),
+ measurementfile.match(2));
+ xml.Attribute(measurementfile.match(3).c_str(),
+ measurementfile.match(4));
+ xml.Attribute("encoding", "base64");
+ std::stringstream ostr;
for (size_t cc = 0; cc < rlen; cc ++ )
{
ostr << encoded_buffer[cc];
@@ -1992,9 +1979,8 @@ void cmCTestTestHandler::GenerateRegressionImages(
ostr << std::endl;
}
}
- ostr
- << "" << std::endl << "\t\t\t"
- << std::endl;
+ xml.Element("Value", ostr.str());
+ xml.EndElement(); // NamedMeasurement
delete [] file_buffer;
delete [] encoded_buffer;
}
@@ -2006,13 +1992,11 @@ void cmCTestTestHandler::GenerateRegressionImages(
{
idx = 2;
}
- ostr
- << "\t\t\tFile " << filename
- << " not found"
- << std::endl;
+ xml.StartElement("NamedMeasurement");
+ xml.Attribute("name", measurementfile.match(idx));
+ xml.Attribute("text", "text/string");
+ xml.Element("Value", "File " + filename + " not found");
+ xml.EndElement();
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "File \"" << filename
<< "\" not found." << std::endl, this->Quiet);
}
diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h
index 623c996d4..14067d5f4 100644
--- a/Source/CTest/cmCTestTestHandler.h
+++ b/Source/CTest/cmCTestTestHandler.h
@@ -18,6 +18,7 @@
#include
class cmMakefile;
+class cmXMLWriter;
/** \class cmCTestTestHandler
* \brief A class that handles ctest -S invocations
@@ -164,10 +165,10 @@ protected:
virtual void GenerateTestCommand(std::vector& args, int test);
int ExecuteCommands(std::vector& vec);
- void WriteTestResultHeader(std::ostream& os, cmCTestTestResult* result);
- void WriteTestResultFooter(std::ostream& os, cmCTestTestResult* result);
+ void WriteTestResultHeader(cmXMLWriter& xml, cmCTestTestResult* result);
+ void WriteTestResultFooter(cmXMLWriter& xml, cmCTestTestResult* result);
// Write attached test files into the xml
- void AttachFiles(std::ostream& os, cmCTestTestResult* result);
+ void AttachFiles(cmXMLWriter& xml, cmCTestTestResult* result);
//! Clean test output to specified length
bool CleanTestOutput(std::string& output, size_t length);
@@ -204,7 +205,7 @@ private:
/**
* Generate the Dart compatible output
*/
- virtual void GenerateDartOutput(std::ostream& os);
+ virtual void GenerateDartOutput(cmXMLWriter& xml);
void PrintLabelSummary();
/**
@@ -270,7 +271,7 @@ private:
cmsys::RegularExpression IncludeTestsRegularExpression;
cmsys::RegularExpression ExcludeTestsRegularExpression;
- void GenerateRegressionImages(std::ostream& ostr, const std::string& xml);
+ void GenerateRegressionImages(cmXMLWriter& xml, const std::string& dart);
cmsys::RegularExpression DartStuff1;
void CheckLabelFilter(cmCTestTestProperties& it);
void CheckLabelFilterExclude(cmCTestTestProperties& it);
diff --git a/Source/CTest/cmCTestUpdateHandler.cxx b/Source/CTest/cmCTestUpdateHandler.cxx
index 10927e78c..8494d28c3 100644
--- a/Source/CTest/cmCTestUpdateHandler.cxx
+++ b/Source/CTest/cmCTestUpdateHandler.cxx
@@ -20,7 +20,7 @@
#include "cmVersion.h"
#include "cmGeneratedFileStream.h"
#include "cmXMLParser.h"
-#include "cmXMLSafe.h"
+#include "cmXMLWriter.h"
#include "cmCLocaleEnvironmentScope.h"
#include "cmCTestVC.h"
@@ -224,24 +224,24 @@ int cmCTestUpdateHandler::ProcessHandler()
bool updated = vc->Update();
std::string buildname = cmCTest::SafeBuildIdField(
this->CTest->GetCTestConfiguration("BuildName"));
- os << "\n"
- << "\n"
- << "\t" << this->CTest->GetCTestConfiguration("Site") << "\n"
- << "\t" << buildname
- << "\n"
- << "\t" << this->CTest->GetCurrentTag() << "-"
- << this->CTest->GetTestModelString() << "" << std::endl;
- os << "\t" << start_time << "\n"
- << "\t" << start_time_time << "\n"
- << "\t"
- << cmXMLSafe(vc->GetUpdateCommandLine()).Quotes(false)
- << "\n"
- << "\t" << cmXMLSafe(
- cmCTestUpdateHandlerUpdateToString(this->UpdateType))
- << "\n";
- vc->WriteXML(os);
+ cmXMLWriter xml(os);
+ xml.StartDocument();
+ xml.StartElement("Update");
+ xml.Attribute("mode", "Client");
+ xml.Attribute("Generator",
+ std::string("ctest-") + cmVersion::GetCMakeVersion());
+ xml.Element("Site", this->CTest->GetCTestConfiguration("Site"));
+ xml.Element("BuildName", buildname);
+ xml.Element("BuildStamp", this->CTest->GetCurrentTag() + "-" +
+ this->CTest->GetTestModelString());
+ xml.Element("StartDateTime", start_time);
+ xml.Element("StartTime", start_time_time);
+ xml.Element("UpdateCommand", vc->GetUpdateCommandLine());
+ xml.Element("UpdateType",
+ cmCTestUpdateHandlerUpdateToString(this->UpdateType));
+
+ vc->WriteXML(xml);
int localModifications = 0;
int numUpdated = vc->GetPathCount(cmCTestVC::PathUpdated);
@@ -265,29 +265,30 @@ int cmCTestUpdateHandler::ProcessHandler()
cmCTestOptionalLog(this->CTest, DEBUG, "End" << std::endl, this->Quiet);
std::string end_time = this->CTest->CurrentTime();
- os << "\t" << end_time << "\n"
- << "\t" << static_cast(cmSystemTools::GetTime())
- << "\n"
- << "" <<
- static_cast((cmSystemTools::GetTime() - elapsed_time_start)/6)/10.0
- << "\n"
- << "\t";
+ xml.Element("EndDateTime", end_time);
+ xml.Element("EndTime", static_cast(cmSystemTools::GetTime()));
+ xml.Element("ElapsedMinutes",
+ static_cast((cmSystemTools::GetTime() - elapsed_time_start)/6)/10.0);
+
+ xml.StartElement("UpdateReturnStatus");
if(localModifications)
{
- os << "Update error: There are modified or conflicting files in the "
- "repository";
+ xml.Content("Update error: "
+ "There are modified or conflicting files in the repository");
cmCTestLog(this->CTest, ERROR_MESSAGE,
" There are modified or conflicting files in the repository"
<< std::endl);
}
if(!updated)
{
- os << "Update command failed:\n" << vc->GetUpdateCommandLine();
+ xml.Content("Update command failed:\n");
+ xml.Content(vc->GetUpdateCommandLine());
cmCTestLog(this->CTest, ERROR_MESSAGE, " Update command failed: "
<< vc->GetUpdateCommandLine() << "\n");
}
- os << "" << std::endl;
- os << "" << std::endl;
+ xml.EndElement(); // UpdateReturnStatus
+ xml.EndElement(); // Update
+ xml.EndDocument();
return numUpdated;
}
diff --git a/Source/CTest/cmCTestUploadHandler.cxx b/Source/CTest/cmCTestUploadHandler.cxx
index 579190a2a..5c6b2290f 100644
--- a/Source/CTest/cmCTestUploadHandler.cxx
+++ b/Source/CTest/cmCTestUploadHandler.cxx
@@ -13,7 +13,7 @@
#include "cmGeneratedFileStream.h"
#include "cmVersion.h"
-#include "cmXMLSafe.h"
+#include "cmXMLWriter.h"
//----------------------------------------------------------------------------
cmCTestUploadHandler::cmCTestUploadHandler()
@@ -47,32 +47,36 @@ int cmCTestUploadHandler::ProcessHandler()
std::string buildname = cmCTest::SafeBuildIdField(
this->CTest->GetCTestConfiguration("BuildName"));
cmCTest::SetOfStrings::const_iterator it;
- ofs << "\n"
- << " \"?>\n"
- << "CTest->GetCurrentTag() << "-"
- << this->CTest->GetTestModelString() << "\" Name=\""
- << this->CTest->GetCTestConfiguration("Site") << "\" Generator=\"ctest"
- << cmVersion::GetCMakeVersion()
- << "\">\n";
- this->CTest->AddSiteProperties(ofs);
- ofs << "\n";
+ " \"");
+ xml.StartElement("Site");
+ xml.Attribute("BuildName", buildname);
+ xml.Attribute("BuildStamp",
+ this->CTest->GetCurrentTag() + "-" + this->CTest->GetTestModelString());
+ xml.Attribute("Name", this->CTest->GetCTestConfiguration("Site"));
+ xml.Attribute("Generator",
+ std::string("ctest") + cmVersion::GetCMakeVersion());
+ this->CTest->AddSiteProperties(xml);
+ xml.StartElement("Upload");
for ( it = this->Files.begin(); it != this->Files.end(); it ++ )
{
cmCTestOptionalLog(this->CTest, OUTPUT,
"\tUpload file: " << *it << std::endl, this->Quiet);
- ofs << "\n"
- << "\n";
- ofs << this->CTest->Base64EncodeFile(*it);
- ofs << "\n\n"
- << "\n";
+ xml.StartElement("File");
+ xml.Attribute("filename", *it);
+ xml.StartElement("Content");
+ xml.Attribute("encoding", "base64");
+ xml.Content(this->CTest->Base64EncodeFile(*it));
+ xml.EndElement(); // Content
+ xml.EndElement(); // File
}
- ofs << "\n"
- << "\n";
+ xml.EndElement(); // Upload
+ xml.EndElement(); // Site
+ xml.EndDocument();
return 0;
}
diff --git a/Source/CTest/cmCTestVC.cxx b/Source/CTest/cmCTestVC.cxx
index 6e93e95c3..8eff4d61b 100644
--- a/Source/CTest/cmCTestVC.cxx
+++ b/Source/CTest/cmCTestVC.cxx
@@ -13,7 +13,7 @@
#include "cmCTest.h"
#include "cmSystemTools.h"
-#include "cmXMLSafe.h"
+#include "cmXMLWriter.h"
#include
@@ -202,7 +202,7 @@ bool cmCTestVC::UpdateImpl()
}
//----------------------------------------------------------------------------
-bool cmCTestVC::WriteXML(std::ostream& xml)
+bool cmCTestVC::WriteXML(cmXMLWriter& xml)
{
this->Log << "--- Begin Revisions ---\n";
bool result = this->WriteXMLUpdates(xml);
@@ -211,7 +211,7 @@ bool cmCTestVC::WriteXML(std::ostream& xml)
}
//----------------------------------------------------------------------------
-bool cmCTestVC::WriteXMLUpdates(std::ostream&)
+bool cmCTestVC::WriteXMLUpdates(cmXMLWriter&)
{
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"* CTest cannot extract updates for this VCS tool.\n");
@@ -219,7 +219,7 @@ bool cmCTestVC::WriteXMLUpdates(std::ostream&)
}
//----------------------------------------------------------------------------
-void cmCTestVC::WriteXMLEntry(std::ostream& xml,
+void cmCTestVC::WriteXMLEntry(cmXMLWriter& xml,
std::string const& path,
std::string const& name,
std::string const& full,
@@ -228,21 +228,19 @@ void cmCTestVC::WriteXMLEntry(std::ostream& xml,
static const char* desc[3] = { "Updated", "Modified", "Conflicting"};
Revision const& rev = f.Rev? *f.Rev : this->Unknown;
std::string prior = f.PriorRev? f.PriorRev->Rev : std::string("Unknown");
- xml << "\t\t<" << desc[f.Status] << ">\n"
- << "\t\t\t" << cmXMLSafe(name) << "\n"
- << "\t\t\t" << cmXMLSafe(path) << "\n"
- << "\t\t\t" << cmXMLSafe(full) << "\n"
- << "\t\t\t" << cmXMLSafe(rev.Date) << "\n"
- << "\t\t\t" << cmXMLSafe(rev.Author) << "\n"
- << "\t\t\t" << cmXMLSafe(rev.EMail) << "\n"
- << "\t\t\t" << cmXMLSafe(rev.Committer) << "\n"
- << "\t\t\t" << cmXMLSafe(rev.CommitterEMail)
- << "\n"
- << "\t\t\t" << cmXMLSafe(rev.CommitDate)
- << "\n"
- << "\t\t\t" << cmXMLSafe(rev.Log) << "\n"
- << "\t\t\t" << cmXMLSafe(rev.Rev) << "\n"
- << "\t\t\t" << cmXMLSafe(prior) << "\n"
- << "\t\t" << desc[f.Status] << ">\n";
+ xml.StartElement(desc[f.Status]);
+ xml.Element("File", name);
+ xml.Element("Directory", path);
+ xml.Element("FullName", full);
+ xml.Element("CheckinDate", rev.Date);
+ xml.Element("Author", rev.Author);
+ xml.Element("Email", rev.EMail);
+ xml.Element("Committer", rev.Committer);
+ xml.Element("CommitterEmail", rev.CommitterEMail);
+ xml.Element("CommitDate", rev.CommitDate);
+ xml.Element("Log", rev.Log);
+ xml.Element("Revision", rev.Rev);
+ xml.Element("PriorRevision", prior);
+ xml.EndElement();
++this->PathCount[f.Status];
}
diff --git a/Source/CTest/cmCTestVC.h b/Source/CTest/cmCTestVC.h
index 9dd06515d..bc8930287 100644
--- a/Source/CTest/cmCTestVC.h
+++ b/Source/CTest/cmCTestVC.h
@@ -15,6 +15,7 @@
#include "cmProcessTools.h"
class cmCTest;
+class cmXMLWriter;
/** \class cmCTestVC
* \brief Base class for version control system handlers
@@ -51,7 +52,7 @@ public:
{ return this->UpdateCommandLine; }
/** Write Update.xml entries for the updates found. */
- bool WriteXML(std::ostream& xml);
+ bool WriteXML(cmXMLWriter& xml);
/** Enumerate non-trivial working tree states during update. */
enum PathStatus { PathUpdated, PathModified, PathConflicting };
@@ -65,7 +66,7 @@ protected:
virtual void NoteOldRevision();
virtual bool UpdateImpl();
virtual void NoteNewRevision();
- virtual bool WriteXMLUpdates(std::ostream& xml);
+ virtual bool WriteXMLUpdates(cmXMLWriter& xml);
#if defined(__SUNPRO_CC) && __SUNPRO_CC <= 0x510
public: // Sun CC 5.1 needs help to allow cmCTestSVN::Revision to see this
@@ -110,7 +111,7 @@ protected:
OutputParser* out, OutputParser* err = 0);
/** Write xml element for one file. */
- void WriteXMLEntry(std::ostream& xml, std::string const& path,
+ void WriteXMLEntry(cmXMLWriter& xml, std::string const& path,
std::string const& name, std::string const& full,
File const& f);
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx
index 7f4b6ad32..e3b7a2bcb 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -28,6 +28,7 @@
#include "cmCTestStartCommand.h"
#include "cmAlgorithms.h"
#include "cmState.h"
+#include "cmXMLWriter.h"
#include "cmCTestBuildHandler.h"
#include "cmCTestBuildAndTestHandler.h"
@@ -1489,7 +1490,7 @@ std::string cmCTest::SafeBuildIdField(const std::string& value)
}
//----------------------------------------------------------------------
-void cmCTest::StartXML(std::ostream& ostr, bool append)
+void cmCTest::StartXML(cmXMLWriter& xml, bool append)
{
if(this->CurrentTag.empty())
{
@@ -1512,42 +1513,45 @@ void cmCTest::StartXML(std::ostream& ostr, bool append)
std::string site = cmCTest::SafeBuildIdField(
this->GetCTestConfiguration("Site"));
- ostr << "\n"
- << "GetCTestConfiguration("Compiler")
- << "\"\n"
+ xml.StartDocument();
+ xml.StartElement("Site");
+ xml.Attribute("BuildName", buildname);
+ xml.BreakAttributes();
+ xml.Attribute("BuildStamp", stamp);
+ xml.Attribute("Name", site);
+ xml.Attribute("Generator",
+ std::string("ctest-") + cmVersion::GetCMakeVersion());
+ if(append)
+ {
+ xml.Attribute("Append", "true");
+ }
+ xml.Attribute("CompilerName", this->GetCTestConfiguration("Compiler"));
#ifdef _COMPILER_VERSION
- << "\tCompilerVersion=\"_COMPILER_VERSION\"\n"
+ xml.Attribute("CompilerVersion", _COMPILER_VERSION);
#endif
- << "\tOSName=\"" << info.GetOSName() << "\"\n"
- << "\tHostname=\"" << info.GetHostname() << "\"\n"
- << "\tOSRelease=\"" << info.GetOSRelease() << "\"\n"
- << "\tOSVersion=\"" << info.GetOSVersion() << "\"\n"
- << "\tOSPlatform=\"" << info.GetOSPlatform() << "\"\n"
- << "\tIs64Bits=\"" << info.Is64Bits() << "\"\n"
- << "\tVendorString=\"" << info.GetVendorString() << "\"\n"
- << "\tVendorID=\"" << info.GetVendorID() << "\"\n"
- << "\tFamilyID=\"" << info.GetFamilyID() << "\"\n"
- << "\tModelID=\"" << info.GetModelID() << "\"\n"
- << "\tProcessorCacheSize=\"" << info.GetProcessorCacheSize() << "\"\n"
- << "\tNumberOfLogicalCPU=\"" << info.GetNumberOfLogicalCPU() << "\"\n"
- << "\tNumberOfPhysicalCPU=\""<< info.GetNumberOfPhysicalCPU() << "\"\n"
- << "\tTotalVirtualMemory=\"" << info.GetTotalVirtualMemory() << "\"\n"
- << "\tTotalPhysicalMemory=\""<< info.GetTotalPhysicalMemory() << "\"\n"
- << "\tLogicalProcessorsPerPhysical=\""
- << info.GetLogicalProcessorsPerPhysical() << "\"\n"
- << "\tProcessorClockFrequency=\""
- << info.GetProcessorClockFrequency() << "\"\n"
- << ">" << std::endl;
- this->AddSiteProperties(ostr);
+ xml.Attribute("OSName", info.GetOSName());
+ xml.Attribute("Hostname", info.GetHostname());
+ xml.Attribute("OSRelease", info.GetOSRelease());
+ xml.Attribute("OSVersion", info.GetOSVersion());
+ xml.Attribute("OSPlatform", info.GetOSPlatform());
+ xml.Attribute("Is64Bits", info.Is64Bits());
+ xml.Attribute("VendorString", info.GetVendorString());
+ xml.Attribute("VendorID", info.GetVendorID());
+ xml.Attribute("FamilyID", info.GetFamilyID());
+ xml.Attribute("ModelID", info.GetModelID());
+ xml.Attribute("ProcessorCacheSize", info.GetProcessorCacheSize());
+ xml.Attribute("NumberOfLogicalCPU", info.GetNumberOfLogicalCPU());
+ xml.Attribute("NumberOfPhysicalCPU", info.GetNumberOfPhysicalCPU());
+ xml.Attribute("TotalVirtualMemory", info.GetTotalVirtualMemory());
+ xml.Attribute("TotalPhysicalMemory", info.GetTotalPhysicalMemory());
+ xml.Attribute("LogicalProcessorsPerPhysical",
+ info.GetLogicalProcessorsPerPhysical());
+ xml.Attribute("ProcessorClockFrequency", info.GetProcessorClockFrequency());
+ this->AddSiteProperties(xml);
}
//----------------------------------------------------------------------
-void cmCTest::AddSiteProperties(std::ostream& ostr)
+void cmCTest::AddSiteProperties(cmXMLWriter& xml)
{
cmCTestScriptHandler* ch =
static_cast(this->GetHandler("script"));
@@ -1563,92 +1567,95 @@ void cmCTest::AddSiteProperties(std::ostream& ostr)
->GetGlobalProperty("SubProject");
if(subproject)
{
- ostr << "\n";
+ xml.StartElement("Subproject");
+ xml.Attribute("name", subproject);
const char* labels =
ch->GetCMake()->GetState()
->GetGlobalProperty("SubProjectLabels");
if(labels)
{
- ostr << " \n";
+ xml.StartElement("Labels");
std::string l = labels;
std::vector args;
cmSystemTools::ExpandListArgument(l, args);
for(std::vector::iterator i = args.begin();
i != args.end(); ++i)
{
- ostr << " \n";
+ xml.Element("Label", *i);
}
- ostr << " \n";
+ xml.EndElement();
}
- ostr << "\n";
+ xml.EndElement();
}
// This code should stay when cdash only does label based sub-projects
const char* label = cm->GetState()->GetGlobalProperty("Label");
if(label)
{
- ostr << "\n";
- ostr << " \n";
- ostr << "\n";
+ xml.StartElement("Labels");
+ xml.Element("Label", label);
+ xml.EndElement();
}
}
-
//----------------------------------------------------------------------
-void cmCTest::EndXML(std::ostream& ostr)
+void cmCTest::EndXML(cmXMLWriter& xml)
{
- ostr << "" << std::endl;
+ xml.EndElement(); // Site
+ xml.EndDocument();
}
//----------------------------------------------------------------------
-int cmCTest::GenerateCTestNotesOutput(std::ostream& os,
+int cmCTest::GenerateCTestNotesOutput(cmXMLWriter& xml,
const cmCTest::VectorOfStrings& files)
{
std::string buildname = cmCTest::SafeBuildIdField(
this->GetCTestConfiguration("BuildName"));
cmCTest::VectorOfStrings::const_iterator it;
- os << "\n"
- << " \"?>\n"
- << "CurrentTag << "-" << this->GetTestModelString() << "\" Name=\""
- << this->GetCTestConfiguration("Site") << "\" Generator=\"ctest"
- << cmVersion::GetCMakeVersion()
- << "\">\n";
- this->AddSiteProperties(os);
- os << "" << std::endl;
+ " \"");
+ xml.StartElement("Site");
+ xml.Attribute("BuildName", buildname);
+ xml.Attribute("BuildStamp", this->CurrentTag+"-"+this->GetTestModelString());
+ xml.Attribute("Name", this->GetCTestConfiguration("Site"));
+ xml.Attribute("Generator",std::string("ctest")+cmVersion::GetCMakeVersion());
+ this->AddSiteProperties(xml);
+ xml.StartElement("Notes");
for ( it = files.begin(); it != files.end(); it ++ )
{
cmCTestLog(this, OUTPUT, "\tAdd file: " << *it << std::endl);
std::string note_time = this->CurrentTime();
- os << "\n"
- << "\n"
- << "" << note_time << "\n"
- << "" << std::endl;
+ xml.StartElement("Note");
+ xml.Attribute("Name", *it);
+ xml.Element("Time", cmSystemTools::GetTime());
+ xml.Element("DateTime", note_time);
+ xml.StartElement("Text");
cmsys::ifstream ifs(it->c_str());
if ( ifs )
{
std::string line;
while ( cmSystemTools::GetLineFromStream(ifs, line) )
{
- os << cmXMLSafe(line) << std::endl;
+ xml.Content(line);
+ xml.Content("\n");
}
ifs.close();
}
else
{
- os << "Problem reading file: " << *it << std::endl;
+ xml.Content("Problem reading file: " + *it + "\n");
cmCTestLog(this, ERROR_MESSAGE, "Problem reading file: " << *it
<< " while creating notes" << std::endl);
}
- os << "\n"
- << "" << std::endl;
+ xml.EndElement(); // Text
+ xml.EndElement(); // Note
}
- os << "\n"
- << "" << std::endl;
+ xml.EndElement(); // Notes
+ xml.EndElement(); // Site
+ xml.EndDocument();
return 1;
}
@@ -1661,8 +1668,8 @@ int cmCTest::GenerateNotesFile(const VectorOfStrings &files)
cmCTestLog(this, ERROR_MESSAGE, "Cannot open notes file" << std::endl);
return 1;
}
-
- this->GenerateCTestNotesOutput(ofs, files);
+ cmXMLWriter xml(ofs);
+ this->GenerateCTestNotesOutput(xml, files);
return 0;
}
diff --git a/Source/cmCTest.h b/Source/cmCTest.h
index 3f033d9e3..db3ea1063 100644
--- a/Source/cmCTest.h
+++ b/Source/cmCTest.h
@@ -24,6 +24,7 @@ class cmGeneratedFileStream;
class cmCTestCommand;
class cmCTestScriptHandler;
class cmCTestStartCommand;
+class cmXMLWriter;
#define cmCTestLog(ctSelf, logType, msg) \
do { \
@@ -273,10 +274,10 @@ public:
static std::string SafeBuildIdField(const std::string& value);
//! Start CTest XML output file
- void StartXML(std::ostream& ostr, bool append);
+ void StartXML(cmXMLWriter& xml, bool append);
//! End CTest XML output file
- void EndXML(std::ostream& ostr);
+ void EndXML(cmXMLWriter& xml);
//! Run command specialized for make and configure. Returns process status
// and retVal is return value or exception.
@@ -420,7 +421,7 @@ public:
/** Direct process output to given streams. */
void SetStreams(std::ostream* out, std::ostream* err)
{ this->StreamOut = out; this->StreamErr = err; }
- void AddSiteProperties(std::ostream& );
+ void AddSiteProperties(cmXMLWriter& xml);
bool GetLabelSummary() { return this->LabelSummary;}
std::string GetCostDataFile();
@@ -553,7 +554,7 @@ private:
bool UpdateCTestConfiguration();
//! Create note from files.
- int GenerateCTestNotesOutput(std::ostream& os,
+ int GenerateCTestNotesOutput(cmXMLWriter& xml,
const VectorOfStrings& files);
//! Check if the argument is the one specified
diff --git a/Source/cmXMLWriter.cxx b/Source/cmXMLWriter.cxx
new file mode 100644
index 000000000..f9b3b491c
--- /dev/null
+++ b/Source/cmXMLWriter.cxx
@@ -0,0 +1,134 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2015 Daniel Pfeifer
+
+ Distributed under the OSI-approved BSD License (the "License");
+ see accompanying file Copyright.txt for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License for more information.
+============================================================================*/
+#include "cmXMLWriter.h"
+#include "cmXMLSafe.h"
+
+#include
+#include
+
+cmXMLWriter::cmXMLWriter(std::ostream& output, std::size_t level)
+: Output(output)
+, Level(level)
+, ElementOpen(false)
+, BreakAttrib(false)
+, IsContent(false)
+{
+}
+
+cmXMLWriter::~cmXMLWriter()
+{
+ assert(this->Elements.empty());
+}
+
+void cmXMLWriter::StartDocument(const char* encoding)
+{
+ this->Output << "";
+}
+
+void cmXMLWriter::EndDocument()
+{
+ assert(this->Elements.empty());
+ this->Output << '\n';
+}
+
+void cmXMLWriter::StartElement(std::string const& name)
+{
+ this->CloseStartElement();
+ this->ConditionalLineBreak(!this->IsContent, this->Elements.size());
+ this->Output << '<' << name;
+ this->Elements.push(name);
+ this->ElementOpen = true;
+ this->BreakAttrib = false;
+}
+
+void cmXMLWriter::EndElement()
+{
+ assert(!this->Elements.empty());
+ if (this->ElementOpen)
+ {
+ this->Output << "/>";
+ }
+ else
+ {
+ this->ConditionalLineBreak(!this->IsContent, this->Elements.size() - 1);
+ this->IsContent = false;
+ this->Output << "" << this->Elements.top() << '>';
+ }
+ this->Elements.pop();
+ this->ElementOpen = false;
+}
+
+void cmXMLWriter::BreakAttributes()
+{
+ this->BreakAttrib = true;
+}
+
+void cmXMLWriter::Comment(const char* comment)
+{
+ this->CloseStartElement();
+ this->ConditionalLineBreak(!this->IsContent, this->Elements.size());
+ this->Output << "";
+}
+
+void cmXMLWriter::CData(std::string const& data)
+{
+ this->PreContent();
+ this->Output << "";
+}
+
+void cmXMLWriter::ProcessingInstruction(const char* target, const char* data)
+{
+ this->CloseStartElement();
+ this->ConditionalLineBreak(!this->IsContent, this->Elements.size());
+ this->Output << "" << target << ' ' << data << "?>";
+}
+
+void cmXMLWriter::FragmentFile(const char* fname)
+{
+ this->CloseStartElement();
+ std::ifstream fin(fname, std::ios::in | std::ios::binary);
+ this->Output << fin.rdbuf();
+}
+
+void cmXMLWriter::ConditionalLineBreak(bool condition, std::size_t indent)
+{
+ if (condition)
+ {
+ this->Output << '\n' << std::string(indent + this->Level, '\t');
+ }
+}
+
+void cmXMLWriter::PreAttribute()
+{
+ assert(this->ElementOpen);
+ this->ConditionalLineBreak(this->BreakAttrib, this->Elements.size());
+ if (!this->BreakAttrib)
+ {
+ this->Output << ' ';
+ }
+}
+
+void cmXMLWriter::PreContent()
+{
+ this->CloseStartElement();
+ this->IsContent = true;
+}
+
+void cmXMLWriter::CloseStartElement()
+{
+ if (this->ElementOpen)
+ {
+ this->ConditionalLineBreak(this->BreakAttrib, this->Elements.size());
+ this->Output << '>';
+ this->ElementOpen = false;
+ }
+}
diff --git a/Source/cmXMLWriter.h b/Source/cmXMLWriter.h
new file mode 100644
index 000000000..c38c0deb7
--- /dev/null
+++ b/Source/cmXMLWriter.h
@@ -0,0 +1,120 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2015 Daniel Pfeifer
+
+ Distributed under the OSI-approved BSD License (the "License");
+ see accompanying file Copyright.txt for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License for more information.
+============================================================================*/
+#ifndef cmXMLWiter_h
+#define cmXMLWiter_h
+
+#include "cmStandardIncludes.h"
+#include "cmXMLSafe.h"
+
+#include
+#include
+#include
+#include
+
+class cmXMLWriter
+{
+public:
+ cmXMLWriter(std::ostream& output, std::size_t level = 0);
+ ~cmXMLWriter();
+
+ void StartDocument(const char* encoding = "UTF-8");
+ void EndDocument();
+
+ void StartElement(std::string const& name);
+ void EndElement();
+
+ void BreakAttributes();
+
+ template
+ void Attribute(const char* name, T const& value)
+ {
+ this->PreAttribute();
+ this->Output << name << "=\"" << SafeAttribute(value) << '"';
+ }
+
+ template
+ void Element(std::string const& name, T const& value)
+ {
+ this->StartElement(name);
+ this->Content(value);
+ this->EndElement();
+ }
+
+ template
+ void Content(T const& content)
+ {
+ this->PreContent();
+ this->Output << SafeContent(content);
+ }
+
+ void Comment(const char* comment);
+
+ void CData(std::string const& data);
+
+ void ProcessingInstruction(const char* target, const char* data);
+
+ void FragmentFile(const char* fname);
+
+private:
+ cmXMLWriter(const cmXMLWriter&);
+ cmXMLWriter& operator=(const cmXMLWriter&);
+
+ void ConditionalLineBreak(bool condition, std::size_t indent);
+
+ void PreAttribute();
+ void PreContent();
+
+ void CloseStartElement();
+
+private:
+ static cmXMLSafe SafeAttribute(const char* value)
+ {
+ return cmXMLSafe(value);
+ }
+
+ static cmXMLSafe SafeAttribute(std::string const& value)
+ {
+ return cmXMLSafe(value);
+ }
+
+ template
+ static T SafeAttribute(T value)
+ {
+ return value;
+ }
+
+ static cmXMLSafe SafeContent(const char* value)
+ {
+ return cmXMLSafe(value).Quotes(false);
+ }
+
+ static cmXMLSafe SafeContent(std::string const& value)
+ {
+ return cmXMLSafe(value).Quotes(false);
+ }
+
+ template
+ static T SafeContent(T value)
+ {
+ return value;
+ }
+
+private:
+ std::ostream& Output;
+ std::stack > Elements;
+ std::size_t Level;
+ bool ElementOpen;
+ bool BreakAttrib;
+ bool IsContent;
+};
+
+#endif