1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#include "parser.h"
30
31#if QT_DEPRECATED_SINCE(5, 15)
32
33#include <qxml.h>
34#include <qregularexpression.h>
35
36QT_WARNING_PUSH
37QT_WARNING_DISABLE_DEPRECATED
38class ContentHandler : public QXmlDefaultHandler
39{
40public:
41 ContentHandler();
42
43 // QXmlContentHandler methods
44 bool startDocument();
45 bool endDocument();
46 bool startElement(const QString &namespaceURI,
47 const QString &localName,
48 const QString &qName,
49 const QXmlAttributes &atts);
50 bool endElement(const QString &namespaceURI,
51 const QString &localName,
52 const QString &qName);
53 bool characters(const QString &ch);
54 void setDocumentLocator(QXmlLocator *locator);
55 bool startPrefixMapping(const QString &prefix, const QString &uri);
56 bool endPrefixMapping(const QString &prefix);
57 bool ignorableWhitespace(const QString &ch);
58 bool processingInstruction(const QString &target, const QString &data);
59 bool skippedEntity(const QString &name);
60
61 // QXmlErrorHandler methods
62 bool warning(const QXmlParseException &exception);
63 bool error(const QXmlParseException &exception);
64 bool fatalError(const QXmlParseException &exception);
65
66 // QXmlDTDHandler methods
67 bool notationDecl(const QString &name, const QString &publicId,
68 const QString &systemId);
69 bool unparsedEntityDecl(const QString &name,
70 const QString &publicId,
71 const QString &systemId,
72 const QString &notationName);
73
74 // QXmlEntityResolver methods
75 bool resolveEntity(const QString &publicId,
76 const QString &systemId,
77 QXmlInputSource *&);
78
79 // QXmlLexicalHandler methods
80 bool startDTD (const QString &name, const QString &publicId, const QString &systemId);
81 bool endDTD();
82 bool startEntity(const QString &name);
83 bool endEntity(const QString &name);
84 bool startCDATA();
85 bool endCDATA();
86 bool comment(const QString &ch);
87
88 // QXmlDeclHandler methods
89 bool attributeDecl(const QString &eName, const QString &aName, const QString &type, const QString &valueDefault, const QString &value);
90 bool internalEntityDecl(const QString &name, const QString &value);
91 bool externalEntityDecl(const QString &name, const QString &publicId, const QString &systemId);
92
93
94 const QString &result() const { return m_result; }
95 const QString &errorMsg() const { return m_error_msg; }
96
97private:
98 QString nestPrefix() const { return QString().fill(c: ' ', size: 3*m_nest); }
99 QString formatAttributes(const QXmlAttributes & atts);
100 QString escapeStr(const QString &s);
101
102 unsigned m_nest;
103 QString m_result, m_error_msg;
104};
105
106ContentHandler::ContentHandler()
107{
108 m_nest = 0;
109}
110
111
112bool ContentHandler::startDocument()
113{
114 m_result += nestPrefix();
115 m_result += "startDocument()\n";
116 ++m_nest;
117 return true;
118}
119
120bool ContentHandler::endDocument()
121{
122 --m_nest;
123 m_result += nestPrefix();
124 m_result += "endDocument()\n";
125 return true;
126}
127
128bool ContentHandler::startElement(const QString &namespaceURI,
129 const QString &localName,
130 const QString &qName,
131 const QXmlAttributes &atts)
132{
133 m_result += nestPrefix();
134 m_result += "startElement(namespaceURI=\"" + escapeStr(s: namespaceURI)
135 + "\", localName=\"" + escapeStr(s: localName)
136 + "\", qName=\"" + escapeStr(s: qName)
137 + "\", atts=[" + formatAttributes(atts) + "])\n";
138 ++m_nest;
139 return true;
140}
141
142QString ContentHandler::escapeStr(const QString &s)
143{
144 QString result = s;
145 result.replace(re: QRegularExpression("\""), after: "\\\"");
146 result.replace(re: QRegularExpression("\\"), after: "\\\\");
147 result.replace(re: QRegularExpression("\n"), after: "\\n");
148 result.replace(re: QRegularExpression("\r"), after: "\\r");
149 result.replace(re: QRegularExpression("\t"), after: "\\t");
150 return result;
151}
152
153QString ContentHandler::formatAttributes(const QXmlAttributes &atts)
154{
155 QString result;
156 for (int i = 0, cnt = atts.count(); i < cnt; ++i) {
157 if (i != 0) result += ", ";
158 result += "{localName=\"" + escapeStr(s: atts.localName(index: i))
159 + "\", qName=\"" + escapeStr(s: atts.qName(index: i))
160 + "\", uri=\"" + escapeStr(s: atts.uri(index: i))
161 + "\", type=\"" + escapeStr(s: atts.type(index: i))
162 + "\", value=\"" + escapeStr(s: atts.value(index: i)) + "\"}";
163 }
164 return result;
165}
166
167bool ContentHandler::endElement(const QString &namespaceURI,
168 const QString &localName,
169 const QString &qName)
170{
171 --m_nest;
172 m_result += nestPrefix();
173 m_result += "endElement(namespaceURI=\"" + escapeStr(s: namespaceURI)
174 + "\", localName=\"" + escapeStr(s: localName)
175 + "\", qName=\"" + escapeStr(s: qName) + "\")\n";
176 return true;
177}
178
179bool ContentHandler::characters(const QString &ch)
180{
181 m_result += nestPrefix();
182 m_result += "characters(ch=\"" + escapeStr(s: ch) + "\")\n";
183 return true;
184}
185
186void ContentHandler::setDocumentLocator(QXmlLocator *locator)
187{
188 m_result += nestPrefix();
189 m_result += "setDocumentLocator(locator={columnNumber="
190 + QString::number(locator->columnNumber())
191 + ", lineNumber=" + QString::number(locator->lineNumber())
192 + "})\n";
193}
194
195bool ContentHandler::startPrefixMapping (const QString &prefix, const QString & uri)
196{
197 m_result += nestPrefix();
198 m_result += "startPrefixMapping(prefix=\"" + escapeStr(s: prefix)
199 + "\", uri=\"" + escapeStr(s: uri) + "\")\n";
200 ++m_nest;
201 return true;
202}
203
204bool ContentHandler::endPrefixMapping(const QString &prefix)
205{
206 --m_nest;
207 m_result += nestPrefix();
208 m_result += "endPrefixMapping(prefix=\"" + escapeStr(s: prefix) + "\")\n";
209 return true;
210}
211
212bool ContentHandler::ignorableWhitespace(const QString & ch)
213{
214 m_result += nestPrefix();
215 m_result += "ignorableWhitespace(ch=\"" + escapeStr(s: ch) + "\")\n";
216 return true;
217}
218
219bool ContentHandler::processingInstruction(const QString &target, const QString &data)
220{
221 m_result += nestPrefix();
222 m_result += "processingInstruction(target=\"" + escapeStr(s: target)
223 + "\", data=\"" + escapeStr(s: data) + "\")\n";
224 return true;
225}
226
227bool ContentHandler::skippedEntity (const QString & name)
228{
229 m_result += nestPrefix();
230 m_result += "skippedEntity(name=\"" + escapeStr(s: name) + "\")\n";
231 return true;
232}
233
234bool ContentHandler::warning(const QXmlParseException & exception)
235{
236 m_error_msg = QString("Warning %1:%2: %3")
237 .arg(a: exception.columnNumber())
238 .arg(a: exception.lineNumber())
239 .arg(a: exception.message());
240 m_result += nestPrefix();
241 m_result += "warning(exception={columnNumber="
242 + QString::number(exception.columnNumber())
243 + ", lineNumber="
244 + QString::number(exception.lineNumber())
245 + ", publicId=\"" + escapeStr(s: exception.publicId())
246 + "\", systemId=\"" + escapeStr(s: exception.systemId())
247 + "\", message=\"" + escapeStr(s: exception.message())
248 + "\"})\n";
249 return true;
250}
251
252bool ContentHandler::error(const QXmlParseException & exception)
253{
254 m_error_msg = QString("Error %1:%2: %3")
255 .arg(a: exception.columnNumber())
256 .arg(a: exception.lineNumber())
257 .arg(a: exception.message());
258 m_result += nestPrefix();
259 m_result += "error(exception={columnNumber="
260 + QString::number(exception.columnNumber())
261 + ", lineNumber="
262 + QString::number(exception.lineNumber())
263 + ", publicId=\"" + escapeStr(s: exception.publicId())
264 + "\", systemId=\"" + escapeStr(s: exception.systemId())
265 + "\", message=\"" + escapeStr(s: exception.message())
266 + "\"})\n";
267 return true;
268}
269
270bool ContentHandler::fatalError(const QXmlParseException & exception)
271{
272 m_error_msg = QString("Fatal error %1:%2: %3")
273 .arg(a: exception.columnNumber())
274 .arg(a: exception.lineNumber())
275 .arg(a: exception.message());
276 m_result += nestPrefix();
277 m_result += "fatalError(exception={columnNumber="
278 + QString::number(exception.columnNumber())
279 + ", lineNumber="
280 + QString::number(exception.lineNumber())
281 + ", publicId=\"" + escapeStr(s: exception.publicId())
282 + "\", systemId=\"" + escapeStr(s: exception.systemId())
283 + "\", message=\"" + escapeStr(s: exception.message())
284 + "\"})\n";
285 return true;
286}
287
288bool ContentHandler::notationDecl(const QString &name,
289 const QString &publicId,
290 const QString &systemId )
291{
292 m_result += nestPrefix();
293 m_result += "notationDecl(name=\"" + escapeStr(s: name) + "\", publicId=\""
294 + escapeStr(s: publicId) + "\", systemId=\""
295 + escapeStr(s: systemId) + "\")\n";
296 return true;
297}
298
299bool ContentHandler::unparsedEntityDecl(const QString &name,
300 const QString &publicId,
301 const QString &systemId,
302 const QString &notationName )
303{
304 m_result += nestPrefix();
305 m_result += "unparsedEntityDecl(name=\"" + escapeStr(s: name)
306 + "\", publicId=\"" + escapeStr(s: publicId)
307 + "\", systemId=\"" + escapeStr(s: systemId)
308 + "\", notationName=\"" + escapeStr(s: notationName)
309 + "\")\n";
310 return true;
311}
312
313bool ContentHandler::resolveEntity(const QString &publicId,
314 const QString &systemId,
315 QXmlInputSource *&)
316{
317 m_result += nestPrefix();
318 m_result += "resolveEntity(publicId=\"" + escapeStr(s: publicId)
319 + "\", systemId=\"" + escapeStr(s: systemId)
320 + "\", ret={})\n";
321 return true;
322}
323
324bool ContentHandler::startDTD ( const QString & name, const QString & publicId, const QString & systemId )
325{
326 m_result += nestPrefix();
327 m_result += "startDTD(name=\"" + escapeStr(s: name)
328 + "\", publicId=\"" + escapeStr(s: publicId)
329 + "\", systemId=\"" + escapeStr(s: systemId) + "\")\n";
330 ++m_nest;
331 return true;
332}
333
334bool ContentHandler::endDTD ()
335{
336 --m_nest;
337 m_result += nestPrefix();
338 m_result += "endDTD()\n";
339 return true;
340}
341
342bool ContentHandler::startEntity ( const QString & name )
343{
344 m_result += nestPrefix();
345 m_result += "startEntity(name=\"" + escapeStr(s: name) + "\")\n";
346 ++m_nest;
347 return true;
348}
349
350bool ContentHandler::endEntity ( const QString & name )
351{
352 --m_nest;
353 m_result += nestPrefix();
354 m_result += "endEntity(name=\"" + escapeStr(s: name) + "\")\n";
355 return true;
356}
357
358bool ContentHandler::startCDATA ()
359{
360 m_result += nestPrefix();
361 m_result += "startCDATA()\n";
362 ++m_nest;
363 return true;
364}
365
366bool ContentHandler::endCDATA ()
367{
368 --m_nest;
369 m_result += nestPrefix();
370 m_result += "endCDATA()\n";
371 return true;
372}
373
374bool ContentHandler::comment ( const QString & ch )
375{
376 m_result += nestPrefix();
377 m_result += "comment(ch=\"" + escapeStr(s: ch) + "\")\n";
378 return true;
379}
380
381bool ContentHandler::attributeDecl(const QString &eName,
382 const QString &aName,
383 const QString &type,
384 const QString &valueDefault,
385 const QString &value)
386{
387 m_result += nestPrefix();
388 m_result += "attributeDecl(eName=\"" + escapeStr(s: eName) + "\", aName=\""
389 + escapeStr(s: aName) + "\", type=\"" + escapeStr(s: type)
390 + "\", valueDefault=\"" + escapeStr(s: valueDefault)
391 + "\", value=\"" + escapeStr(s: value) + "\")\n";
392 return true;
393}
394
395bool ContentHandler::internalEntityDecl(const QString &name,
396 const QString &value)
397{
398 m_result += nestPrefix();
399 m_result += "internatlEntityDecl(name=\"" + escapeStr(s: name)
400 + "\", value=\"" + escapeStr(s: value) + "\")\n";
401 return true;
402}
403
404bool ContentHandler::externalEntityDecl(const QString &name,
405 const QString &publicId,
406 const QString &systemId)
407{
408 m_result += nestPrefix();
409 m_result += "externalEntityDecl(name=\"" + escapeStr(s: name)
410 + "\", publicId=\"" + escapeStr(s: publicId)
411 + "\", systemId=\"" + escapeStr(s: systemId) + "\")\n";
412 return true;
413}
414
415Parser::Parser()
416{
417 handler = new ContentHandler;
418 setContentHandler(handler);
419 setDTDHandler(handler);
420 setDeclHandler(handler);
421 setEntityResolver(handler);
422 setErrorHandler(handler);
423 setLexicalHandler(handler);
424}
425
426Parser::~Parser()
427{
428 delete handler;
429}
430
431bool Parser::parseFile(QFile *file)
432{
433 QXmlInputSource source(file);
434 return parse(input: source);
435}
436
437QString Parser::result() const
438{
439 return handler->result();
440}
441
442QString Parser::errorMsg() const
443{
444 return handler->errorMsg();
445}
446
447QT_WARNING_POP
448#endif // QT_DEPRECATED_SINCE(5, 15)
449

source code of qtbase/tests/auto/xml/sax/qxmlsimplereader/parser/parser.cpp