Skip to content

Commit cac1bff

Browse files
committed
encode strings for xml use
1 parent daabc34 commit cac1bff

File tree

1 file changed

+34
-13
lines changed

1 file changed

+34
-13
lines changed

include/formatters/junit_xml.hpp

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,31 @@ namespace CppSpec::Formatters {
1313
// JUnit XML header
1414
constexpr static auto junit_xml_header = R"(<?xml version="1.0" encoding="UTF-8"?>)";
1515

16-
struct XMLSerializable {
17-
virtual ~XMLSerializable() = default;
18-
[[nodiscard]] virtual std::string to_xml() const = 0;
19-
};
16+
inline std::string encode_xml(const std::string& data) {
17+
std::string buffer;
18+
for (char c : data) {
19+
switch (c) {
20+
case '<':
21+
buffer += "&lt;";
22+
break;
23+
case '>':
24+
buffer += "&gt;";
25+
break;
26+
case '&':
27+
buffer += "&amp;";
28+
break;
29+
case '"':
30+
buffer += "&quot;";
31+
break;
32+
case '\'':
33+
buffer += "&apos;";
34+
break;
35+
default:
36+
buffer += c;
37+
}
38+
}
39+
return buffer;
40+
}
2041

2142
namespace JUnitNodes {
2243
struct Result {
@@ -42,8 +63,8 @@ struct Result {
4263
}
4364

4465
[[nodiscard]] std::string to_xml() const {
45-
return std::format(R"( <{} message="{}" type="{}">{}</{}>)", status_string(), message, type, text,
46-
status_string());
66+
return std::format(R"( <{} message="{}" type="{}">{}</{}>)", status_string(), encode_xml(message),
67+
encode_xml(type), encode_xml(text), status_string());
4768
}
4869
};
4970

@@ -58,8 +79,8 @@ struct TestCase {
5879

5980
[[nodiscard]] std::string to_xml() const {
6081
auto start =
61-
std::format(R"( <testcase name="{}" classname="{}" assertions="{}" time="{:f}" file="{}" line="{}")", name,
62-
classname, assertions, time.count(), file, line);
82+
std::format(R"( <testcase name="{}" classname="{}" assertions="{}" time="{:f}" file="{}" line="{}")",
83+
encode_xml(name), encode_xml(classname), assertions, time.count(), file, line);
6384
if (results.empty()) {
6485
return start + "/>";
6586
}
@@ -99,10 +120,10 @@ struct TestSuite {
99120

100121
std::stringstream ss;
101122
ss << " "
102-
<< std::format(R"(<testsuite id="{}" name="{}" time="{:f}" timestamp="{}" tests="{}" failures="{}">)", id, name,
103-
time.count(), timestamp_str, tests, failures);
123+
<< std::format(R"(<testsuite id="{}" name="{}" time="{:f}" timestamp="{}" tests="{}" failures="{}">)", id,
124+
encode_xml(name), time.count(), timestamp_str, tests, failures);
104125
ss << std::endl;
105-
for (const auto& test_case : cases) {
126+
for (const TestCase& test_case : cases) {
106127
ss << test_case.to_xml() << std::endl;
107128
}
108129
ss << " </testsuite>";
@@ -127,8 +148,8 @@ struct TestSuites {
127148
[[nodiscard]] std::string to_xml() const {
128149
std::stringstream ss;
129150
auto timestamp_str = std::format("{0:%F}T{0:%T}", timestamp);
130-
ss << std::format(R"(<testsuites name="{}" tests="{}" failures="{}" time="{:f}" timestamp="{}">)", name, tests,
131-
failures, time.count(), timestamp_str);
151+
ss << std::format(R"(<testsuites name="{}" tests="{}" failures="{}" time="{:f}" timestamp="{}">)", encode_xml(name),
152+
tests, failures, time.count(), timestamp_str);
132153
ss << std::endl;
133154
for (const TestSuite& suite : suites) {
134155
ss << suite.to_xml() << std::endl;

0 commit comments

Comments
 (0)