XmlWriter reverts to XML 1.0.

Character encodings that are not valid in XML 1.0 are instead written using C-style escapes
This commit is contained in:
Phil Nash 2017-02-06 16:00:05 +00:00
parent 7db4d8d90c
commit 1f271c9944
5 changed files with 36 additions and 40 deletions

View file

@ -57,8 +57,11 @@ namespace Catch {
default:
// Escape control chars - based on contribution by @espenalb in PR #465 and
// by @mrpi PR #588
if ( ( c >= 0 && c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' )
os << "&#x" << std::uppercase << std::hex << std::setfill('0') << std::setw(2) << static_cast<int>( c ) << ';';
if ( ( c >= 0 && c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' ) {
// see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
os << "\\x" << std::uppercase << std::hex << std::setfill('0') << std::setw(2)
<< static_cast<int>( c );
}
else
os << c;
}
@ -112,20 +115,17 @@ namespace Catch {
XmlWriter()
: m_tagIsOpen( false ),
m_needsNewline( false ),
m_os( &Catch::cout() )
m_os( Catch::cout() )
{
// We encode control characters, which requires
// XML 1.1
// see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
*m_os << "<?xml version=\"1.1\" encoding=\"UTF-8\"?>\n";
writeDeclaration();
}
XmlWriter( std::ostream& os )
: m_tagIsOpen( false ),
m_needsNewline( false ),
m_os( &os )
m_os( os )
{
*m_os << "<?xml version=\"1.1\" encoding=\"UTF-8\"?>\n";
writeDeclaration();
}
~XmlWriter() {
@ -136,7 +136,7 @@ namespace Catch {
XmlWriter& startElement( std::string const& name ) {
ensureTagClosed();
newlineIfNecessary();
stream() << m_indent << '<' << name;
m_os << m_indent << '<' << name;
m_tags.push_back( name );
m_indent += " ";
m_tagIsOpen = true;
@ -153,25 +153,25 @@ namespace Catch {
newlineIfNecessary();
m_indent = m_indent.substr( 0, m_indent.size()-2 );
if( m_tagIsOpen ) {
stream() << "/>";
m_os << "/>";
m_tagIsOpen = false;
}
else {
stream() << m_indent << "</" << m_tags.back() << ">";
m_os << m_indent << "</" << m_tags.back() << ">";
}
stream() << std::endl;
m_os << std::endl;
m_tags.pop_back();
return *this;
}
XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) {
if( !name.empty() && !attribute.empty() )
stream() << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"';
m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"';
return *this;
}
XmlWriter& writeAttribute( std::string const& name, bool attribute ) {
stream() << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"';
m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"';
return *this;
}
@ -187,8 +187,8 @@ namespace Catch {
bool tagWasOpen = m_tagIsOpen;
ensureTagClosed();
if( tagWasOpen && indent )
stream() << m_indent;
stream() << XmlEncode( text );
m_os << m_indent;
m_os << XmlEncode( text );
m_needsNewline = true;
}
return *this;
@ -196,39 +196,35 @@ namespace Catch {
XmlWriter& writeComment( std::string const& text ) {
ensureTagClosed();
stream() << m_indent << "<!--" << text << "-->";
m_os << m_indent << "<!--" << text << "-->";
m_needsNewline = true;
return *this;
}
XmlWriter& writeBlankLine() {
ensureTagClosed();
stream() << '\n';
m_os << '\n';
return *this;
}
void setStream( std::ostream& os ) {
m_os = &os;
}
private:
XmlWriter( XmlWriter const& );
void operator=( XmlWriter const& );
std::ostream& stream() {
return *m_os;
void writeDeclaration() {
m_os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
}
void ensureTagClosed() {
if( m_tagIsOpen ) {
stream() << ">\n";
m_os << ">\n";
m_tagIsOpen = false;
}
}
void newlineIfNecessary() {
if( m_needsNewline ) {
stream() << '\n';
m_os << '\n';
m_needsNewline = false;
}
}
@ -237,7 +233,7 @@ namespace Catch {
bool m_needsNewline;
std::vector<std::string> m_tags;
std::string m_indent;
std::ostream* m_os;
std::ostream& m_os;
};
}