1
2
3
4
5
6 #include <sngxml/dom/Parser.hpp>
7 #include <sngxml/dom/Element.hpp>
8 #include <sngxml/dom/CharacterData.hpp>
9 #include <sngxml/xml/XmlParserInterface.hpp>
10 #include <soulng/util/MappedInputFile.hpp>
11 #include <soulng/util/Unicode.hpp>
12 #include <soulng/util/TextUtils.hpp>
13 #include <string>
14 #include <stack>
15 #include <sstream>
16
17 namespace sngxml { namespace dom {
18
19 using namespace sngxml::xml;
20 using namespace soulng::util;
21 using namespace soulng::unicode;
22
23 class DomDocumentHandler : public XmlContentHandler
24 {
25 public:
26 DomDocumentHandler();
27 std::unique_ptr<Document> GetDocument();
28 void StartDocument() override;
29 void EndDocument() override;
30 void Version(const std::u32string& xmlVersion) override;
31 void Standalone(bool standalone) override;
32 void Encoding(const std::u32string& encoding) override;
33 void Text(const std::u32string& text) override;
34 void Comment(const std::u32string& comment) override;
35 void PI(const std::u32string& target, const std::u32string& data) override;
36 void CDataSection(const std::u32string& data) override;
37 void StartElement(const std::u32string& namespaceUri, const std::u32string& localName, const std::u32string& qualifiedName, const Attributes& attributes) override;
38 void EndElement(const std::u32string& namespaceUri, const std::u32string& localName, const std::u32string& qualifiedName) override;
39 void SkippedEntity(const std::u32string& entityName) override;
40 private:
41 std::unique_ptr<Document> document;
42 std::unique_ptr<Element> currentElement;
43 std::stack<std::std::unique_ptr<Element>>elementStack;
44 std::u32string textContent;
45 void AddTextContent();
46 void AddTextContent(bool addSpace);
47 };
48
49 DomDocumentHandler::DomDocumentHandler() : document(new Document())
50 {
51 }
52
53 std::std::unique_ptr<Document>DomDocumentHandler::GetDocument()
54 {
55 return std::move(document);
56 }
57
58 void DomDocumentHandler::AddTextContent()
59 {
60 AddTextContent(false);
61 }
62
63 void DomDocumentHandler::AddTextContent(bool addSpace)
64 {
65 if (currentElement)
66 {
67 std::u32string text = TrimAll(textContent);
68 if (!text.empty())
69 {
70 if (addSpace)
71 {
72 text.append(1, ' ');
73 }
74 std::unique_ptr<dom::Text> textNode(new dom::Text(text));
75 currentElement->AppendChild(std::move(textNode));
76 }
77 }
78 textContent.clear();
79 }
80
81 void DomDocumentHandler::StartDocument()
82 {
83
84 }
85
86 void DomDocumentHandler::EndDocument()
87 {
88
89 }
90
91 void DomDocumentHandler::Version(const std::u32string& xmlVersion)
92 {
93 document->SetXmlVersion(xmlVersion);
94 }
95
96 void DomDocumentHandler::Standalone(bool standalone)
97 {
98 document->SetXmlStandalone(standalone);
99 }
100
101 void DomDocumentHandler::Encoding(const std::u32string& encoding)
102 {
103 document->SetXmlEncoding(encoding);
104 }
105
106 void DomDocumentHandler::Text(const std::u32string& text)
107 {
108 textContent.append(text);
109 }
110
111 void DomDocumentHandler::Comment(const std::u32string& comment)
112 {
113 AddTextContent();
114 std::unique_ptr<dom::Comment> commentNode(new dom::Comment(comment));
115 if (currentElement)
116 {
117 currentElement->AppendChild(std::move(commentNode));
118 }
119 else
120 {
121 document->AppendChild(std::move(commentNode));
122 }
123 }
124
125 void DomDocumentHandler::PI(const std::u32string& target, const std::u32string& data)
126 {
127 AddTextContent();
128 std::unique_ptr<dom::ProcessingInstruction> processingInstructionNode(new dom::ProcessingInstruction(target, data));
129 if (currentElement)
130 {
131 currentElement->AppendChild(std::move(processingInstructionNode));
132 }
133 else
134 {
135 document->AppendChild(std::move(processingInstructionNode));
136 }
137 }
138
139 void DomDocumentHandler::CDataSection(const std::u32string& data)
140 {
141 AddTextContent();
142 std::unique_ptr<dom::CDataSection> cdataSection(new dom::CDataSection(data));
143 if (currentElement)
144 {
145 currentElement->AppendChild(std::move(cdataSection));
146 }
147 else
148 {
149 document->AppendChild(std::move(cdataSection));
150 }
151 }
152
153 void DomDocumentHandler::StartElement(const std::u32string& namespaceUri, const std::u32string& localName, const std::u32string& qualifiedName, const Attributes& attributes)
154 {
155 AddTextContent(true);
156 elementStack.push(std::move(currentElement));
157 std::map<std::u32string, std::std::unique_ptr<Attr>>attrs;
158 for (const Attribute& attr : attributes)
159 {
160 attrs[attr.QualifiedName()] = std::unique_ptr<Attr>(new Attr(attr.QualifiedName(), attr.Value()));
161 }
162 currentElement.reset(new Element(qualifiedName, std::move(attrs)));
163 currentElement->InternalSetOwnerDocument(document.get());
164 if (!namespaceUri.empty())
165 {
166 currentElement->InternalSetNamespaceUri(namespaceUri);
167 }
168 }
169
170 void DomDocumentHandler::EndElement(const std::u32string& namespaceUri, const std::u32string& localName, const std::u32string& qualifiedName)
171 {
172 AddTextContent();
173 std::unique_ptr<Element> parentElement = std::move(elementStack.top());
174 elementStack.pop();
175 if (parentElement)
176 {
177 parentElement->AppendChild(std::move(currentElement));
178 currentElement = std::move(parentElement);
179 }
180 else
181 {
182 document->AppendChild(std::move(currentElement));
183 }
184 }
185
186 void DomDocumentHandler::SkippedEntity(const std::u32string& entityName)
187 {
188
189 }
190
191 std::std::unique_ptr<Document>ParseDocument(conststd::u32string&content, conststd::string&systemId)
192 {
193 return ParseDocument(content, systemId, Flags::none);
194 }
195
196 std::std::unique_ptr<Document>ParseDocument(conststd::u32string&content, conststd::string&systemId, Flags flags)
197 {
198 DomDocumentHandler domDocumentHandler;
199 sngxml::xml::Flags xmlFlags = sngxml::xml::Flags::none;
200 if ((flags & Flags::debug) != Flags::none)
201 {
202 xmlFlags = xmlFlags | sngxml::xml::Flags::debug;
203 }
204 ParseXmlContent(content, systemId, &domDocumentHandler, xmlFlags);
205 return domDocumentHandler.GetDocument();
206 }
207
208 std::std::unique_ptr<Document>ReadDocument(conststd::string&fileName)
209 {
210 return ReadDocument(fileName, Flags::none);
211 }
212
213 std::std::unique_ptr<Document>ReadDocument(conststd::string&fileName, Flagsflags)
214 {
215 std::u32string content = ToUtf32(ReadFile(fileName));
216 return ParseDocument(content, fileName, flags);
217 }
218
219 void SendDocument(soulng::util::TcpSocket& socket, Document& document)
220 {
221 std::stringstream sstream;
222 CodeFormatter formatter(sstream);
223 document.Write(formatter);
224 Write(socket, sstream.str());
225 }
226
227 std::std::unique_ptr<Document>ReceiveDocument(soulng::util::TcpSocket&socket)
228 {
229 std::string str = ReadStr(socket);
230 if (str.empty()) return std::unique_ptr<Document>();
231 std::u32string content = ToUtf32(str);
232 std::unique_ptr<Document> doc = ParseDocument(content, "socket");
233 return doc;
234 }
235
236 } }