1 // Copyright (C) 2012-2019 The VPaint Developers.
2 // See the COPYRIGHT file at the top-level directory of this distribution
3 // and at https://github.com/dalboris/vpaint/blob/master/COPYRIGHT
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 
17 #ifndef XMLSTREAMWRITER_H
18 #define XMLSTREAMWRITER_H
19 
20 #include <QXmlStreamWriter>
21 
22 /// \class XmlStreamWriter
23 /// Writes an XML document to a file.
24 ///
25 /// This class overrides Qt default behaviour to achieve desired indenting style,
26 /// for better human-readability in our use-case.
27 ///
28 /// For instance, instead of:
29 ///
30 ///     <tag attr1="value1" attr2="value2"/>
31 ///
32 /// We want:
33 ///
34 ///     <tag
35 ///       attr1="value1"
36 ///       attr2="value2"/>
37 ///
38 /// Also, we want to allow writing multiline attribute values without escaping '\n',
39 /// such that instead of:
40 ///
41 ///     <tag
42 ///       attr="a long attribute&#10;spanning three&#10;different lines"/>
43 ///
44 /// We get:
45 ///
46 ///     <tag
47 ///       attr="a long attribute
48 ///             spanning three
49 ///             different lines"/>
50 ///
51 /// This is XML compliant but one should be aware that newlines characters will be
52 /// replaced by whitespaces by any compliant XML parser, i.e. it will be interpreted as:
53 ///
54 ///     "a long attribute             spanning three             different lines"
55 ///
56 /// This is OK because in the specification of the VEC file formats, newlines in attributes
57 /// are never significant, and consecutive whitespaces are equivalent to single whitespaces.
58 
59 class XmlStreamWriter : public QXmlStreamWriter
60 {
61 public:
62     XmlStreamWriter(QIODevice * device);
63     ~XmlStreamWriter();
64 
65     // Writes a start element
66     void writeStartElement(const QString & qualifiedName);
67     void writeEndElement();
68 
69     // Writes an element attributes
70     void writeAttribute(const QString & qualifiedName, const QString & value);
71     void writeAttribute(const QXmlStreamAttribute & attribute);
72     void writeAttributes(const QXmlStreamAttributes & attributes);
73 
74 private:
75     int indentLevel_;
76 
77     // Raw-write to device, without escaping XML characters
78     void write(const QString & string) const;
79 
80     // Escape special characters
81     static QString escaped(const QString & s);
82 
83     // Escape special characters except newlines
84     static QString escapedExceptNewlines(const QString & s);
85 
86 };
87 
88 
89 #endif // XMLSTREAMWRITER_H
90