]>
Commit | Line | Data |
---|---|---|
78d14f80 VS |
1 | ///////////////////////////////////////////////////////////////////////////// |
2 | // Name: xmlwrite.cpp | |
3 | // Purpose: wxXmlDocument - XML text writer | |
4 | // Author: Vaclav Slavik | |
5 | // Created: 2001/04/30 | |
6 | // RCS-ID: $Id$ | |
7 | // Copyright: (c) 2001 Vaclav Slavik | |
8 | // Licence: wxWindows licence | |
9 | ///////////////////////////////////////////////////////////////////////////// | |
10 | ||
11 | #ifdef __GNUG__ | |
12 | // nothing - already in xml.cpp | |
13 | #endif | |
14 | ||
15 | // For compilers that support precompilation, includes "wx.h". | |
16 | #include "wx/wxprec.h" | |
17 | ||
18 | #ifdef __BORLANDC__ | |
19 | #pragma hdrstop | |
20 | #endif | |
21 | ||
22 | #include "wx/wfstream.h" | |
23 | #include "wx/intl.h" | |
24 | #include "wx/log.h" | |
25 | #include "wx/strconv.h" | |
26 | #include "wx/xrc/xml.h" | |
27 | #include "wx/xrc/xmlio.h" | |
28 | ||
29 | // write string to output: | |
1419ea47 VS |
30 | inline static void OutputString(wxOutputStream& stream, const wxString& str, |
31 | wxMBConv *convMem, wxMBConv *convFile) | |
78d14f80 VS |
32 | { |
33 | if (str.IsEmpty()) return; | |
34 | #if wxUSE_UNICODE | |
1419ea47 VS |
35 | const wxW2MBbuf *buf = str.mb_str(convFile ? *convFile : wxConvUTF8); |
36 | stream.Write((const char*)buf, strlen((const char*)buf)); | |
78d14f80 | 37 | #else |
1419ea47 VS |
38 | if ( convFile == NULL ) |
39 | stream.Write(str.mb_str(), str.Len()); | |
40 | else | |
41 | { | |
42 | wxString str2(str.wc_str(*convMem), *convFile); | |
43 | stream.Write(str2.mb_str(), str2.Len()); | |
44 | } | |
78d14f80 VS |
45 | #endif |
46 | } | |
47 | ||
48 | // Same as above, but create entities first. | |
49 | // Translates '<' to "<", '>' to ">" and '&' to "&" | |
1419ea47 VS |
50 | static void OutputStringEnt(wxOutputStream& stream, const wxString& str, |
51 | wxMBConv *convMem, wxMBConv *convFile) | |
78d14f80 VS |
52 | { |
53 | wxString buf; | |
54 | size_t i, last, len; | |
480505bc | 55 | wxChar c; |
78d14f80 VS |
56 | |
57 | len = str.Len(); | |
58 | last = 0; | |
59 | for (i = 0; i < len; i++) | |
60 | { | |
61 | c = str.GetChar(i); | |
480505bc VS |
62 | if (c == wxT('<') || c == wxT('>') || |
63 | (c == wxT('&') && str.Mid(i+1, 4) != wxT("amp;"))) | |
78d14f80 | 64 | { |
1419ea47 | 65 | OutputString(stream, str.Mid(last, i - last), convMem, convFile); |
78d14f80 VS |
66 | switch (c) |
67 | { | |
1419ea47 VS |
68 | case wxT('<'): |
69 | OutputString(stream, wxT("<"), NULL, NULL); | |
70 | break; | |
71 | case wxT('>'): | |
72 | OutputString(stream, wxT(">"), NULL, NULL); | |
73 | break; | |
74 | case wxT('&'): | |
75 | OutputString(stream, wxT("&"), NULL, NULL); | |
76 | break; | |
78d14f80 VS |
77 | default: break; |
78 | } | |
79 | last = i + 1; | |
80 | } | |
81 | } | |
1419ea47 | 82 | OutputString(stream, str.Mid(last, i - last), convMem, convFile); |
78d14f80 VS |
83 | } |
84 | ||
85 | inline static void OutputIndentation(wxOutputStream& stream, int indent) | |
86 | { | |
87 | wxString str = wxT("\n"); | |
88 | for (int i = 0; i < indent; i++) | |
89 | str << wxT(' ') << wxT(' '); | |
1419ea47 | 90 | OutputString(stream, str, NULL, NULL); |
78d14f80 VS |
91 | } |
92 | ||
1419ea47 VS |
93 | static void OutputNode(wxOutputStream& stream, wxXmlNode *node, int indent, |
94 | wxMBConv *convMem, wxMBConv *convFile) | |
78d14f80 VS |
95 | { |
96 | wxXmlNode *n, *prev; | |
97 | wxXmlProperty *prop; | |
98 | ||
99 | switch (node->GetType()) | |
100 | { | |
101 | case wxXML_TEXT_NODE: | |
1419ea47 | 102 | OutputStringEnt(stream, node->GetContent(), convMem, convFile); |
78d14f80 VS |
103 | break; |
104 | ||
105 | case wxXML_ELEMENT_NODE: | |
1419ea47 VS |
106 | OutputString(stream, wxT("<"), NULL, NULL); |
107 | OutputString(stream, node->GetName(), NULL, NULL); | |
78d14f80 VS |
108 | |
109 | prop = node->GetProperties(); | |
110 | while (prop) | |
111 | { | |
112 | OutputString(stream, wxT(" ") + prop->GetName() + | |
1419ea47 VS |
113 | wxT("=\"") + prop->GetValue() + wxT("\""), |
114 | NULL, NULL); | |
78d14f80 VS |
115 | // FIXME - what if prop contains '"'? |
116 | prop = prop->GetNext(); | |
117 | } | |
118 | ||
119 | if (node->GetChildren()) | |
120 | { | |
1419ea47 | 121 | OutputString(stream, wxT(">"), NULL, NULL); |
78d14f80 VS |
122 | prev = NULL; |
123 | n = node->GetChildren(); | |
124 | while (n) | |
125 | { | |
126 | if (n && n->GetType() != wxXML_TEXT_NODE) | |
127 | OutputIndentation(stream, indent + 1); | |
1419ea47 | 128 | OutputNode(stream, n, indent + 1, convMem, convFile); |
78d14f80 VS |
129 | prev = n; |
130 | n = n->GetNext(); | |
131 | } | |
132 | if (prev && prev->GetType() != wxXML_TEXT_NODE) | |
133 | OutputIndentation(stream, indent); | |
1419ea47 VS |
134 | OutputString(stream, wxT("</"), NULL, NULL); |
135 | OutputString(stream, node->GetName(), NULL, NULL); | |
136 | OutputString(stream, wxT(">"), NULL, NULL); | |
78d14f80 VS |
137 | } |
138 | else | |
1419ea47 | 139 | OutputString(stream, wxT("/>"), NULL, NULL); |
78d14f80 VS |
140 | break; |
141 | ||
142 | case wxXML_COMMENT_NODE: | |
1419ea47 VS |
143 | OutputString(stream, wxT("<!--"), NULL, NULL); |
144 | OutputString(stream, node->GetContent(), convMem, convFile); | |
145 | OutputString(stream, wxT("-->"), NULL, NULL); | |
78d14f80 VS |
146 | break; |
147 | ||
148 | default: | |
149 | wxFAIL_MSG(wxT("unsupported node type")); | |
150 | } | |
151 | } | |
152 | ||
153 | bool wxXmlIOHandlerWriter::Save(wxOutputStream& stream, const wxXmlDocument& doc) | |
154 | { | |
155 | if (!doc.IsOk()) | |
156 | return FALSE; | |
157 | ||
158 | wxString s; | |
159 | ||
1419ea47 VS |
160 | wxMBConv *convMem = NULL, *convFile = NULL; |
161 | #if wxUSE_UNICODE | |
162 | convFile = new wxCSConv(doc.GetFileEncoding()); | |
163 | #else | |
164 | if ( doc.GetFileEncoding() != doc.GetEncoding() ) | |
165 | { | |
166 | convFile = new wxCSConv(doc.GetFileEncoding()); | |
167 | convMem = new wxCSConv(doc.GetEncoding()); | |
168 | } | |
169 | #endif | |
170 | ||
171 | s.Printf(wxT("<?xml version=\"%s\" encoding=\"%s\"?>\n"), | |
172 | doc.GetVersion().c_str(), doc.GetFileEncoding().c_str()); | |
173 | OutputString(stream, s, NULL, NULL); | |
174 | ||
175 | OutputNode(stream, doc.GetRoot(), 0, convMem, convFile); | |
176 | OutputString(stream, wxT("\n"), NULL, NULL); | |
78d14f80 | 177 | |
1419ea47 VS |
178 | if ( convFile ) |
179 | delete convFile; | |
180 | if ( convMem ) | |
181 | delete convMem; | |
78d14f80 VS |
182 | |
183 | return TRUE; | |
184 | } |