19 namespace relpipe { |
19 namespace relpipe { |
20 namespace in { |
20 namespace in { |
21 namespace xmltable { |
21 namespace xmltable { |
22 |
22 |
23 #include <codecvt> |
23 #include <codecvt> |
|
24 #include <vector> |
24 |
25 |
25 #include <libxml++-2.6/libxml++/libxml++.h> |
26 #include <libxml++-2.6/libxml++/libxml++.h> |
26 #include <yaml.h> |
27 #include <yaml.h> |
27 |
28 |
28 class XMLDocumentConstructor { |
29 class XMLDocumentConstructor { |
29 private: |
30 private: |
30 std::istream* input = nullptr; |
31 std::istream* input = nullptr; |
31 xmlpp::DomParser* parser = nullptr; |
32 xmlpp::DomParser* parser = nullptr; |
32 yaml_parser_t yamlParser; |
33 yaml_parser_t yamlParser; |
33 |
34 |
|
35 enum class Mode { |
|
36 ROOT, |
|
37 SEQUENCE, |
|
38 MAPPING, |
|
39 MAP_KEY |
|
40 }; |
|
41 |
|
42 xmlpp::Element* current; |
|
43 std::vector<Mode> mode; |
|
44 |
34 static int readFromInput(void* instance, unsigned char* buffer, size_t size, size_t* length) { |
45 static int readFromInput(void* instance, unsigned char* buffer, size_t size, size_t* length) { |
35 std::istream* input = ((XMLDocumentConstructor*) instance)->input; |
46 std::istream* input = ((XMLDocumentConstructor*) instance)->input; |
36 input->read((char*) buffer, size); |
47 input->read((char*) buffer, size); |
37 *length = input->gcount(); |
48 *length = input->gcount(); |
38 return (input->good() || input->eof()) ? 1 : 0; |
49 return (input->good() || input->eof()) ? 1 : 0; |
39 } |
50 } |
40 |
51 |
41 /** |
52 /** |
42 * Both YAML and XML strings are in UTF-8. |
53 * Both YAML and XML strings are in UTF-8. |
43 */ |
54 */ |
44 const char* y2x(yaml_char_t* value) { |
55 const char* y2x(yaml_char_t* value) { |
45 return value ? (const char*) value : ""; |
56 return value ? (const char*) value : ""; |
|
57 } |
|
58 |
|
59 const std::string y2xname(yaml_char_t* value) { |
|
60 // FIXME: escaping, assure valid XML names |
|
61 //return std::string("name_") + y2x(value); |
|
62 return y2x(value); |
|
63 } |
|
64 |
|
65 xmlpp::Element* parentOrSelf(xmlpp::Element* current) { |
|
66 return current->get_parent() == nullptr ? current : current->get_parent(); |
46 } |
67 } |
47 |
68 |
48 public: |
69 public: |
49 |
70 |
50 XMLDocumentConstructor(std::istream* input, xmlpp::DomParser* parser) : input(input), parser(parser) { |
71 XMLDocumentConstructor(std::istream* input, xmlpp::DomParser* parser) : input(input), parser(parser) { |
68 return; |
90 return; |
69 } |
91 } |
70 |
92 |
71 |
93 |
72 if (event.type == YAML_STREAM_END_EVENT) { |
94 if (event.type == YAML_STREAM_END_EVENT) { |
73 xmlpp::Element* e = root->add_child("YAML_STREAM_END_EVENT"); |
95 std::cerr << "YAML_STREAM_END_EVENT" << std::endl; |
74 yaml_event_delete(&event); |
96 yaml_event_delete(&event); |
75 break; |
97 break; |
76 } else if (event.type == YAML_STREAM_START_EVENT) { |
98 } else if (event.type == YAML_STREAM_START_EVENT) { |
77 xmlpp::Element* e = root->add_child("YAML_STREAM_START_EVENT"); |
99 std::cerr << "YAML_STREAM_START_EVENT" << std::endl; |
78 } else if (event.type == YAML_NO_EVENT) { |
100 } else if (event.type == YAML_NO_EVENT) { |
79 xmlpp::Element* e = root->add_child("YAML_NO_EVENT"); |
101 std::cerr << "YAML_NO_EVENT" << std::endl; |
|
102 current->add_child("null"); // TODO: null? |
80 } else if (event.type == YAML_DOCUMENT_START_EVENT) { |
103 } else if (event.type == YAML_DOCUMENT_START_EVENT) { |
81 xmlpp::Element* e = root->add_child("YAML_DOCUMENT_START_EVENT"); |
104 std::cerr << "YAML_DOCUMENT_START_EVENT" << std::endl; |
82 } else if (event.type == YAML_DOCUMENT_END_EVENT) { |
105 } else if (event.type == YAML_DOCUMENT_END_EVENT) { |
83 xmlpp::Element* e = root->add_child("YAML_DOCUMENT_END_EVENT"); |
106 std::cerr << "YAML_DOCUMENT_END_EVENT" << std::endl; |
84 } else if (event.type == YAML_ALIAS_EVENT) { |
107 } else if (event.type == YAML_ALIAS_EVENT) { |
85 xmlpp::Element* e = root->add_child("YAML_ALIAS_EVENT"); |
108 std::cerr << "YAML_ALIAS_EVENT" << std::endl; |
|
109 // TODO: alias? |
86 } else if (event.type == YAML_SCALAR_EVENT) { |
110 } else if (event.type == YAML_SCALAR_EVENT) { |
87 xmlpp::Element* e = root->add_child("YAML_SCALAR_EVENT"); |
111 if (mode.back() == Mode::SEQUENCE) { |
88 e->set_attribute("value", y2x(event.data.scalar.value)); |
112 std::cerr << "YAML_SCALAR_EVENT: Mode::SEQUENCE: " << event.data.scalar.value << std::endl; |
89 e->set_attribute("anchor", y2x(event.data.scalar.anchor)); |
113 current->add_child("item")->add_child_text(y2x(event.data.scalar.value)); |
90 e->set_attribute("tag", y2x(event.data.scalar.tag)); |
114 } else if (mode.back() == Mode::MAPPING) { |
91 e->set_attribute("style", std::to_string(event.data.scalar.style)); |
115 std::cerr << "YAML_SCALAR_EVENT: Mode::MAPPING: " << event.data.scalar.value << std::endl; |
|
116 current = current->add_child(y2xname(event.data.scalar.value)); |
|
117 mode.push_back(Mode::MAP_KEY); |
|
118 } else if (mode.back() == Mode::MAP_KEY) { |
|
119 std::cerr << "YAML_SCALAR_EVENT: Mode::MAP_KEY: " << event.data.scalar.value << std::endl; |
|
120 current->add_child_text(y2x(event.data.scalar.value)); |
|
121 current = parentOrSelf(current); |
|
122 mode.pop_back(); |
|
123 } else { |
|
124 std::cerr << "YAML_SCALAR_EVENT: ???" << std::endl; |
|
125 } |
|
126 |
92 } else if (event.type == YAML_SEQUENCE_START_EVENT) { |
127 } else if (event.type == YAML_SEQUENCE_START_EVENT) { |
93 xmlpp::Element* e = root->add_child("YAML_SEQUENCE_START_EVENT"); |
128 std::cerr << "YAML_SEQUENCE_START_EVENT" << std::endl; |
94 e->set_attribute("style", std::to_string(event.data.sequence_start.style)); |
129 if (mode.back() == Mode::MAP_KEY) mode.pop_back(); |
|
130 mode.push_back(Mode::SEQUENCE); |
95 } else if (event.type == YAML_SEQUENCE_END_EVENT) { |
131 } else if (event.type == YAML_SEQUENCE_END_EVENT) { |
96 xmlpp::Element* e = root->add_child("YAML_SEQUENCE_END_EVENT"); |
132 std::cerr << "YAML_SEQUENCE_END_EVENT" << std::endl; |
|
133 current = parentOrSelf(current); |
|
134 mode.pop_back(); // TODO: assert sequence? |
97 } else if (event.type == YAML_MAPPING_START_EVENT) { |
135 } else if (event.type == YAML_MAPPING_START_EVENT) { |
98 xmlpp::Element* e = root->add_child("YAML_MAPPING_START_EVENT"); |
136 |
|
137 if (mode.back() == Mode::SEQUENCE) { |
|
138 std::cerr << "YAML_MAPPING_START_EVENT: Mode::SEQUENCE" << std::endl; |
|
139 current = current->add_child("item"); |
|
140 } else if (mode.back() == Mode::MAP_KEY) { |
|
141 std::cerr << "YAML_MAPPING_START_EVENT: Mode::MAP_KEY" << std::endl; |
|
142 mode.pop_back(); |
|
143 } else { |
|
144 std::cerr << "YAML_MAPPING_START_EVENT: Mode::?" << std::endl; |
|
145 // TODO: map might be a key of another map → wrap/nest |
|
146 } |
|
147 |
|
148 mode.push_back(Mode::MAPPING); |
99 } else if (event.type == YAML_MAPPING_END_EVENT) { |
149 } else if (event.type == YAML_MAPPING_END_EVENT) { |
100 xmlpp::Element* e = root->add_child("YAML_MAPPING_END_EVENT"); |
150 std::cerr << "YAML_MAPPING_END_EVENT" << std::endl; |
|
151 current = parentOrSelf(current); |
|
152 mode.pop_back(); // TODO: assert map? |
|
153 } else { |
|
154 std::cerr << "???" << std::endl; |
101 } |
155 } |
102 |
156 |
103 yaml_event_delete(&event); |
157 yaml_event_delete(&event); |
104 } |
158 } |
105 |
159 |