|
1 #pragma once |
|
2 |
|
3 #include <string> |
|
4 #include <vector> |
|
5 #include <iostream> |
|
6 #include <sstream> |
|
7 #include <locale> |
|
8 #include <codecvt> |
|
9 #include <regex> |
|
10 |
|
11 #include <relpipe/reader/typedefs.h> |
|
12 #include <relpipe/reader/TypeId.h> |
|
13 #include <relpipe/reader/handlers/RelationalReaderStringHandler.h> |
|
14 #include <relpipe/reader/handlers/AttributeMetadata.h> |
|
15 |
|
16 namespace relpipe { |
|
17 namespace out { |
|
18 namespace tabular { |
|
19 |
|
20 using namespace relpipe::reader; |
|
21 |
|
22 class XmlHandler : public handlers::RelationalReaderStringHadler { |
|
23 private: |
|
24 std::wstring_convert<std::codecvt_utf8<wchar_t>> convertor; // XML output will be always in UTF-8 |
|
25 const char* INDENT = "\t"; |
|
26 |
|
27 std::ostream &output; |
|
28 |
|
29 std::vector<TypeId> columnTypes; |
|
30 std::vector<string_t> columnTypeCodes; |
|
31 std::vector<string_t> columnNames; |
|
32 std::vector<integer_t> columnWidths; |
|
33 std::vector<string_t> values; // all values are saved here and processed at the end of the relation |
|
34 integer_t columnCount = 0; |
|
35 |
|
36 |
|
37 |
|
38 const string_t escapeXmlText(const string_t &value, const char* color) { |
|
39 std::wstringstream result; |
|
40 |
|
41 for (auto & ch : value) { |
|
42 switch (ch) { |
|
43 // FIXME: xml escaping |
|
44 case L'&': result << L"&"; |
|
45 break; |
|
46 default: result << ch; |
|
47 } |
|
48 } |
|
49 |
|
50 return result.str(); |
|
51 } |
|
52 |
|
53 public: |
|
54 |
|
55 XmlHandler(std::ostream& output) : output(output) { |
|
56 } |
|
57 |
|
58 void startRelation(string_t name, std::vector<handlers::AttributeMetadata> attributes) override { |
|
59 output << convertor.to_bytes(name) << ": (XML)" << endl; |
|
60 columnCount = attributes.size(); |
|
61 columnTypes.resize(columnCount); |
|
62 columnTypeCodes.resize(columnCount); |
|
63 columnNames.resize(columnCount); |
|
64 columnWidths.resize(columnCount, 0); |
|
65 for (int i = 0; i < attributes.size(); i++) { |
|
66 columnNames[i] = attributes[i].getAttributeName(); |
|
67 columnTypes[i] = attributes[i].getTypeId(); |
|
68 columnTypeCodes[i] = attributes[i].getTypeName(); |
|
69 } |
|
70 } |
|
71 |
|
72 void attribute(const string_t& value) override { |
|
73 integer_t i = values.size() % columnCount; |
|
74 values.push_back(value); |
|
75 columnWidths[i] = max(columnWidths[i], value.length()); |
|
76 } |
|
77 |
|
78 void endOfPipe() { |
|
79 |
|
80 } |
|
81 |
|
82 }; |
|
83 |
|
84 } |
|
85 } |
|
86 } |