]> git.saurik.com Git - wxWidgets.git/blob - src/xrc/xmlwrite.cpp
no message
[wxWidgets.git] / src / xrc / xmlwrite.cpp
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:
30 inline static void OutputString(wxOutputStream& stream, const wxString& str)
31 {
32 if (str.IsEmpty()) return;
33 #if wxUSE_UNICODE
34 const char *buf = str.mb_str(wxConvUTF8);
35 stream.Write(buf, strlen(buf));
36 #else
37 stream.Write(str.mb_str(), str.Len());
38 #endif
39 }
40
41 // Same as above, but create entities first.
42 // Translates '<' to "&lt;", '>' to "&gt;" and '&' to "&amp;"
43 static void OutputStringEnt(wxOutputStream& stream, const wxString& str)
44 {
45 wxString buf;
46 size_t i, last, len;
47 char c;
48
49 len = str.Len();
50 last = 0;
51 for (i = 0; i < len; i++)
52 {
53 c = str.GetChar(i);
54 if (c == '<' || c == '>' ||
55 (c == '&' && str.Mid(i+1, 4) != wxT("amp;")))
56 {
57 OutputString(stream, str.Mid(last, i - last));
58 switch (c)
59 {
60 case '<': OutputString(stream, wxT("&lt;")); break;
61 case '>': OutputString(stream, wxT("&gt;")); break;
62 case '&': OutputString(stream, wxT("&amp;")); break;
63 default: break;
64 }
65 last = i + 1;
66 }
67 }
68 OutputString(stream, str.Mid(last, i - last));
69 }
70
71 inline static void OutputIndentation(wxOutputStream& stream, int indent)
72 {
73 wxString str = wxT("\n");
74 for (int i = 0; i < indent; i++)
75 str << wxT(' ') << wxT(' ');
76 OutputString(stream, str);
77 }
78
79 static void OutputNode(wxOutputStream& stream, wxXmlNode *node, int indent)
80 {
81 wxXmlNode *n, *prev;
82 wxXmlProperty *prop;
83
84 switch (node->GetType())
85 {
86 case wxXML_TEXT_NODE:
87 OutputStringEnt(stream, node->GetContent());
88 break;
89
90 case wxXML_ELEMENT_NODE:
91 OutputString(stream, wxT("<"));
92 OutputString(stream, node->GetName());
93
94 prop = node->GetProperties();
95 while (prop)
96 {
97 OutputString(stream, wxT(" ") + prop->GetName() +
98 wxT("=\"") + prop->GetValue() + wxT("\""));
99 // FIXME - what if prop contains '"'?
100 prop = prop->GetNext();
101 }
102
103 if (node->GetChildren())
104 {
105 OutputString(stream, wxT(">"));
106 prev = NULL;
107 n = node->GetChildren();
108 while (n)
109 {
110 if (n && n->GetType() != wxXML_TEXT_NODE)
111 OutputIndentation(stream, indent + 1);
112 OutputNode(stream, n, indent + 1);
113 prev = n;
114 n = n->GetNext();
115 }
116 if (prev && prev->GetType() != wxXML_TEXT_NODE)
117 OutputIndentation(stream, indent);
118 OutputString(stream, wxT("</"));
119 OutputString(stream, node->GetName());
120 OutputString(stream, wxT(">"));
121 }
122 else
123 OutputString(stream, wxT("/>"));
124 break;
125
126 case wxXML_COMMENT_NODE:
127 OutputString(stream, wxT("<!--"));
128 OutputString(stream, node->GetContent());
129 OutputString(stream, wxT("-->"));
130 break;
131
132 default:
133 wxFAIL_MSG(wxT("unsupported node type"));
134 }
135 }
136
137 bool wxXmlIOHandlerWriter::Save(wxOutputStream& stream, const wxXmlDocument& doc)
138 {
139 if (!doc.IsOk())
140 return FALSE;
141
142 wxString s;
143
144 s = wxT("<?xml version=\"") + doc.GetVersion() +
145 wxT("\" encoding=\"utf-8\"?>\n");
146 OutputString(stream, s);
147
148 OutputNode(stream, doc.GetRoot(), 0);
149 OutputString(stream, wxT("\n"));
150
151 return TRUE;
152 }