44 |
45 |
45 class RelpipeSaxHandler : public xercesc::DefaultHandler { |
46 class RelpipeSaxHandler : public xercesc::DefaultHandler { |
46 private: |
47 private: |
47 unique_ptr<RelationalWriter> writer; |
48 unique_ptr<RelationalWriter> writer; |
48 |
49 |
|
50 std::wstring_convert<std::codecvt_utf8<wchar_t>> convertor; // TODO: support also other encodings. |
|
51 |
|
52 string_t toString(const XMLCh * const chars) { |
|
53 // XMLCh = char16_t |
|
54 // „All XML data is handled within Xerces-C++ as strings of XMLCh characters. Regardless of the size of the type chosen, the data stored in variables of type XMLCh will always be utf-16 encoded values.“ |
|
55 // see https://xerces.apache.org/xerces-c/program-others-3.html |
|
56 // other solution (depends on boost): https://flylib.com/books/en/2.131.1/working_with_xerces_strings.html |
|
57 |
|
58 // TODO: review this text conversion and test on various platforms |
|
59 char* x = XMLString::transcode(chars); |
|
60 string s = string(x); |
|
61 XMLString::release(&x); |
|
62 return convertor.from_bytes(s); |
|
63 } |
|
64 |
49 public: |
65 public: |
50 |
66 |
51 RelpipeSaxHandler(std::ostream& output) : DefaultHandler(), writer(Factory::create(output)) { |
67 RelpipeSaxHandler(std::ostream& output) : DefaultHandler(), writer(Factory::create(output)) { |
52 } |
68 } |
53 |
69 |
54 void startDocument() override { |
70 void startDocument() override { |
55 //XMLString:: |
71 //XMLString:: |
56 // TODO: remove demo |
72 // TODO: remove demo |
57 writer->startRelation(L"xml",{ |
73 writer->startRelation(L"xml",{ |
58 {L"event", TypeId::STRING}, |
74 {L"event", TypeId::STRING}, |
59 {L"data", TypeId::STRING}, |
75 {L"uri", TypeId::STRING}, |
|
76 {L"localname", TypeId::STRING}, |
|
77 {L"qname", TypeId::STRING}, |
|
78 {L"chars", TypeId::STRING} |
60 }, true); |
79 }, true); |
61 } |
80 } |
62 |
81 |
63 void startElement(const XMLCh * const uri, const XMLCh * const localname, const XMLCh * const qname, const Attributes& attrs) override { |
82 void startElement(const XMLCh * const uri, const XMLCh * const localname, const XMLCh * const qname, const Attributes& attrs) override { |
64 writer->writeAttribute(L"startElement"); |
83 writer->writeAttribute(L"startElement"); |
|
84 writer->writeAttribute(toString(uri)); |
|
85 writer->writeAttribute(toString(localname)); |
|
86 writer->writeAttribute(toString(qname)); |
65 writer->writeAttribute(L""); |
87 writer->writeAttribute(L""); |
|
88 |
|
89 for (int i = 0; i < attrs.getLength(); i++) { |
|
90 writer->writeAttribute(L"attribute"); |
|
91 writer->writeAttribute(toString(attrs.getURI(i))); |
|
92 writer->writeAttribute(toString(attrs.getLocalName(i))); |
|
93 writer->writeAttribute(toString(attrs.getQName(i))); |
|
94 writer->writeAttribute(toString(attrs.getValue(i))); |
|
95 } |
66 } |
96 } |
67 |
97 |
68 void endElement(const XMLCh * const uri, const XMLCh * const localname, const XMLCh * const qname) override { |
98 void endElement(const XMLCh * const uri, const XMLCh * const localname, const XMLCh * const qname) override { |
69 writer->writeAttribute(L"endElement"); |
99 writer->writeAttribute(L"endElement"); |
|
100 writer->writeAttribute(toString(uri)); |
|
101 writer->writeAttribute(toString(localname)); |
|
102 writer->writeAttribute(toString(qname)); |
70 writer->writeAttribute(L""); |
103 writer->writeAttribute(L""); |
71 } |
104 } |
72 |
105 |
73 void characters(const XMLCh * const chars, const XMLSize_t length) override { |
106 void characters(const XMLCh * const chars, const XMLSize_t length) override { |
74 writer->writeAttribute(L"characters"); |
107 writer->writeAttribute(L"characters"); |
75 writer->writeAttribute(to_wstring(length)); |
108 writer->writeAttribute(L""); |
|
109 writer->writeAttribute(L""); |
|
110 writer->writeAttribute(L""); |
|
111 writer->writeAttribute(toString(chars)); |
|
112 } |
|
113 |
|
114 void comment(const XMLCh * const chars, const XMLSize_t length) override { |
|
115 writer->writeAttribute(L"comment"); |
|
116 writer->writeAttribute(L""); |
|
117 writer->writeAttribute(L""); |
|
118 writer->writeAttribute(L""); |
|
119 writer->writeAttribute(toString(chars)); |
|
120 } |
|
121 |
|
122 void startCDATA() override { |
|
123 writer->writeAttribute(L"startCDATA"); |
|
124 writer->writeAttribute(L""); |
|
125 writer->writeAttribute(L""); |
|
126 writer->writeAttribute(L""); |
|
127 writer->writeAttribute(L""); |
|
128 } |
|
129 |
|
130 void endCDATA() override { |
|
131 writer->writeAttribute(L"endCDATA"); |
|
132 writer->writeAttribute(L""); |
|
133 writer->writeAttribute(L""); |
|
134 writer->writeAttribute(L""); |
|
135 writer->writeAttribute(L""); |
76 } |
136 } |
77 |
137 |
78 void endDocument() override { |
138 void endDocument() override { |
79 writer->writeAttribute(L"endDocument"); |
139 writer->writeAttribute(L"endDocument"); |
|
140 writer->writeAttribute(L""); |
|
141 writer->writeAttribute(L""); |
|
142 writer->writeAttribute(L""); |
80 writer->writeAttribute(L""); |
143 writer->writeAttribute(L""); |
81 } |
144 } |
82 |
145 |
83 }; |
146 }; |
84 |
147 |
87 void process(std::istream& input, std::ostream& output) { |
150 void process(std::istream& input, std::ostream& output) { |
88 XMLPlatformUtils::Initialize(); |
151 XMLPlatformUtils::Initialize(); |
89 unique_ptr<SAX2XMLReader> parser(XMLReaderFactory::createXMLReader()); |
152 unique_ptr<SAX2XMLReader> parser(XMLReaderFactory::createXMLReader()); |
90 parser->setFeature(XMLUni::fgSAX2CoreValidation, true); |
153 parser->setFeature(XMLUni::fgSAX2CoreValidation, true); |
91 parser->setFeature(XMLUni::fgSAX2CoreNameSpaces, true); |
154 parser->setFeature(XMLUni::fgSAX2CoreNameSpaces, true); |
|
155 // TODO: optional unbuffered mode for more fluent output? |
|
156 // http://xerces.apache.org/xerces-c/program-sax2-3.html#SAX2Features |
|
157 // parser->setProperty(XMLUni::fgXercesLowWaterMark, ...); |
|
158 // parser->setInputBufferSize(...); |
92 |
159 |
93 RelpipeSaxHandler saxHandler(output); |
160 RelpipeSaxHandler saxHandler(output); |
94 parser->setContentHandler(&saxHandler); |
161 parser->setContentHandler(&saxHandler); |
|
162 parser->setLexicalHandler(&saxHandler); // TODO: remove – needed only for comments |
95 parser->setErrorHandler(&saxHandler); |
163 parser->setErrorHandler(&saxHandler); |
96 |
164 |
97 StreamInputSource inputSource(input); |
165 StreamInputSource inputSource(input); |
98 |
166 |
99 parser->parse(inputSource); |
167 parser->parse(inputSource); |