Use TinyXML to write XML files

This commit is contained in:
PKEuS 2013-08-07 16:30:55 +02:00
parent a9a5dc0354
commit 758d68519d
4 changed files with 69 additions and 88 deletions

View File

@ -1729,11 +1729,11 @@ void XMLDocument::PrintError() const
} }
XMLPrinter::XMLPrinter( FILE* file, bool compact ) : XMLPrinter::XMLPrinter( FILE* file, bool compact, int depth ) :
_elementJustOpened( false ), _elementJustOpened( false ),
_firstElement( true ), _firstElement( true ),
_fp( file ), _fp( file ),
_depth( 0 ), _depth( depth ),
_textDepth( -1 ), _textDepth( -1 ),
_processEntities( true ), _processEntities( true ),
_compactMode( compact ) _compactMode( compact )
@ -1858,6 +1858,8 @@ void XMLPrinter::OpenElement( const char* name )
if ( _textDepth < 0 && !_firstElement && !_compactMode ) { if ( _textDepth < 0 && !_firstElement && !_compactMode ) {
Print( "\n" ); Print( "\n" );
}
if ( !_compactMode ) {
PrintSpace( _depth ); PrintSpace( _depth );
} }

View File

@ -14,6 +14,7 @@ not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation software in a product, an acknowledgment in the product documentation
would be appreciated but is not required. would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and 2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software. must not be misrepresented as being the original software.
@ -125,11 +126,9 @@ class XMLDocument;
class XMLElement; class XMLElement;
class XMLAttribute; class XMLAttribute;
class XMLComment; class XMLComment;
class XMLNode;
class XMLText; class XMLText;
class XMLDeclaration; class XMLDeclaration;
class XMLUnknown; class XMLUnknown;
class XMLPrinter; class XMLPrinter;
/* /*
@ -1884,7 +1883,7 @@ public:
If 'compact' is set to true, then output is created If 'compact' is set to true, then output is created
with only required whitespace and newlines. with only required whitespace and newlines.
*/ */
XMLPrinter( FILE* file=0, bool compact = false ); XMLPrinter( FILE* file=0, bool compact = false, int depth = 0 );
~XMLPrinter() {} ~XMLPrinter() {}
/** If streaming, write the BOM and declaration. */ /** If streaming, write the BOM and declaration. */

View File

@ -22,6 +22,8 @@
#include "tokenlist.h" #include "tokenlist.h"
#include "token.h" #include "token.h"
#include <tinyxml2.h>
#include <cassert> #include <cassert>
#include <sstream> #include <sstream>
#include <vector> #include <vector>
@ -177,23 +179,23 @@ std::string ErrorLogger::ErrorMessage::getXMLHeader(int xml_version)
{ {
// xml_version 1 is the default xml format // xml_version 1 is the default xml format
tinyxml2::XMLPrinter printer;
// standard xml header // standard xml header
std::ostringstream ostr; printer.PushDeclaration("xml version=\"1.0\" encoding=\"UTF-8\"");
ostr << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
// version 1 header
if (xml_version <= 1) {
ostr << "<results>";
}
// header
printer.OpenElement("results");
// version 2 header // version 2 header
else { if (xml_version == 2) {
ostr << "<results version=\"" << xml_version << "\">\n"; printer.PushAttribute("version", xml_version);
ostr << " <cppcheck version=\"" << CppCheck::version() << "\"/>\n"; printer.OpenElement("cppcheck");
ostr << " <errors>"; printer.PushAttribute("version", CppCheck::version());
printer.CloseElement();
printer.OpenElement("errors");
} }
return ostr.str(); return std::string(printer.CStr()) + '>';
} }
std::string ErrorLogger::ErrorMessage::getXMLFooter(int xml_version) std::string ErrorLogger::ErrorMessage::getXMLFooter(int xml_version)
@ -201,71 +203,49 @@ std::string ErrorLogger::ErrorMessage::getXMLFooter(int xml_version)
return (xml_version<=1) ? "</results>" : " </errors>\n</results>"; return (xml_version<=1) ? "</results>" : " </errors>\n</results>";
} }
static std::string stringToXml(std::string s)
{
// convert a string so it can be save as xml attribute data
std::string::size_type pos = 0;
while ((pos = s.find_first_of("<>&\"\n", pos)) != std::string::npos) {
if (s[pos] == '<')
s.insert(pos + 1, "&lt;");
else if (s[pos] == '>')
s.insert(pos + 1, "&gt;");
else if (s[pos] == '&')
s.insert(pos + 1, "&amp;");
else if (s[pos] == '"')
s.insert(pos + 1, "&quot;");
else if (s[pos] == '\n')
s.insert(pos + 1, "&#xa;");
s.erase(pos, 1);
++pos;
}
return s;
}
std::string ErrorLogger::ErrorMessage::toXML(bool verbose, int version) const std::string ErrorLogger::ErrorMessage::toXML(bool verbose, int version) const
{ {
// Save this ErrorMessage as an XML element
std::ostringstream xml;
// The default xml format // The default xml format
if (version == 1) { if (version == 1) {
// No inconclusive messages in the xml version 1 // No inconclusive messages in the xml version 1
if (_inconclusive) if (_inconclusive)
return ""; return "";
xml << "<error"; tinyxml2::XMLPrinter printer(0, false, 1);
printer.OpenElement("error");
if (!_callStack.empty()) { if (!_callStack.empty()) {
xml << " file=\"" << stringToXml(_callStack.back().getfile()) << "\""; printer.PushAttribute("file", _callStack.back().getfile().c_str());
xml << " line=\"" << _callStack.back().line << "\""; printer.PushAttribute("line", _callStack.back().line);
} }
xml << " id=\"" << _id << "\""; printer.PushAttribute("id", _id.c_str());
xml << " severity=\"" << (_severity == Severity::error ? "error" : "style") << "\""; printer.PushAttribute("severity", (_severity == Severity::error ? "error" : "style"));
xml << " msg=\"" << stringToXml(verbose ? _verboseMessage : _shortMessage) << "\""; printer.PushAttribute("msg", (verbose ? _verboseMessage : _shortMessage).c_str());
xml << "/>"; printer.CloseElement();
return printer.CStr();
} }
// The xml format you get when you use --xml-version=2 // The xml format you get when you use --xml-version=2
else if (version == 2) { else if (version == 2) {
xml << " <error"; tinyxml2::XMLPrinter printer(0, false, 2);
xml << " id=\"" << _id << "\""; printer.OpenElement("error");
xml << " severity=\"" << Severity::toString(_severity) << "\""; printer.PushAttribute("id", _id.c_str());
xml << " msg=\"" << stringToXml(_shortMessage) << "\""; printer.PushAttribute("severity", Severity::toString(_severity).c_str());
xml << " verbose=\"" << stringToXml(_verboseMessage) << "\""; printer.PushAttribute("msg", _shortMessage.c_str());
printer.PushAttribute("verbose", _verboseMessage.c_str());
if (_inconclusive) if (_inconclusive)
xml << " inconclusive=\"true\""; printer.PushAttribute("inconclusive", "true");
xml << ">" << std::endl;
for (std::list<FileLocation>::const_reverse_iterator it = _callStack.rbegin(); it != _callStack.rend(); ++it) { for (std::list<FileLocation>::const_reverse_iterator it = _callStack.rbegin(); it != _callStack.rend(); ++it) {
xml << " <location"; printer.OpenElement("location");
xml << " file=\"" << stringToXml((*it).getfile()) << "\""; printer.PushAttribute("file", (*it).getfile().c_str());
xml << " line=\"" << (*it).line << "\""; printer.PushAttribute("line", (*it).line);
xml << "/>" << std::endl; printer.CloseElement();
}
printer.CloseElement();
return printer.CStr();
} }
xml << " </error>"; return "";
}
return xml.str();
} }
void ErrorLogger::ErrorMessage::findAndReplace(std::string &source, const std::string &searchFor, const std::string &replaceWith) void ErrorLogger::ErrorMessage::findAndReplace(std::string &source, const std::string &searchFor, const std::string &replaceWith)