]>
git.saurik.com Git - wxWidgets.git/blob - src/xrc/xmlexpat.cpp
47be0b67d19c88d13be68daa07a50fffd78871c9
1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxXmlDocument - XML reader via Expat
4 // Author: Vaclav Slavik
7 // Copyright: (c) 2001 Vaclav Slavik
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
12 // nothing - already in xml.cpp
15 // For compilers that support precompilation, includes "wx.h".
16 #include "wx/wxprec.h"
22 #include "wx/wfstream.h"
25 #include "wx/strconv.h"
26 #include "wx/xrc/xmlio.h"
34 - handle unknown encodings
35 - process all elements, including CDATA
36 - XML resources should automatically select desired encoding based on
37 runtime environment (?) (would need BIN and BINZ formats modification,
43 // converts Expat-produced string in UTF-8 into wxString.
44 inline static wxString
CharToString(const char *s
, size_t len
= wxSTRING_MAXLEN
)
47 return wxString(s
, wxConvUTF8
, len
);
49 return wxString(s
, len
);
53 bool wxXmlIOHandlerExpat::CanLoad(wxInputStream
& stream
)
57 stream
.Read(cheader
, 6);
58 stream
.SeekI(-6, wxFromCurrent
);
59 return (strcmp(cheader
, "<?xml ") == 0);
63 struct wxXmlParsingContext
67 wxXmlNode
*lastAsText
;
72 static void StartElementHnd(void *userData
, const char *name
, const char **atts
)
74 wxXmlParsingContext
*ctx
= (wxXmlParsingContext
*)userData
;
75 wxXmlNode
*node
= new wxXmlNode(wxXML_ELEMENT_NODE
, CharToString(name
));
76 const char **a
= atts
;
79 node
->AddProperty(CharToString(a
[0]), CharToString(a
[1]));
82 if (ctx
->root
== NULL
)
85 ctx
->node
->AddChild(node
);
87 ctx
->lastAsText
= NULL
;
90 static void EndElementHnd(void *userData
, const char* WXUNUSED(name
))
92 wxXmlParsingContext
*ctx
= (wxXmlParsingContext
*)userData
;
94 ctx
->node
= ctx
->node
->GetParent();
95 ctx
->lastAsText
= NULL
;
98 static void TextHnd(void *userData
, const char *s
, int len
)
100 wxXmlParsingContext
*ctx
= (wxXmlParsingContext
*)userData
;
101 char *buf
= new char[len
+ 1];
104 memcpy(buf
, s
, (size_t)len
);
108 ctx
->lastAsText
->SetContent(ctx
->lastAsText
->GetContent() +
113 bool whiteOnly
= TRUE
;
114 for (char *c
= buf
; *c
!= '\0'; c
++)
115 if (*c
!= ' ' && *c
!= '\t' && *c
!= '\n' && *c
!= '\r')
122 ctx
->lastAsText
= new wxXmlNode(wxXML_TEXT_NODE
, wxT("text"),
124 ctx
->node
->AddChild(ctx
->lastAsText
);
131 static void CommentHnd(void *userData
, const char *data
)
133 wxXmlParsingContext
*ctx
= (wxXmlParsingContext
*)userData
;
137 // VS: ctx->node == NULL happens if there is a comment before
138 // the root element (e.g. wxDesigner's output). We ignore such
139 // comments, no big deal...
140 ctx
->node
->AddChild(new wxXmlNode(wxXML_COMMENT_NODE
,
141 wxT("comment"), CharToString(data
)));
143 ctx
->lastAsText
= NULL
;
146 static void DefaultHnd(void *userData
, const char *s
, int len
)
149 if (len
> 6 && memcmp(s
, "<?xml ", 6) == 0)
151 wxXmlParsingContext
*ctx
= (wxXmlParsingContext
*)userData
;
153 wxString buf
= CharToString(s
, (size_t)len
);
155 pos
= buf
.Find(wxT("encoding="));
156 if (pos
!= wxNOT_FOUND
)
157 ctx
->encoding
= buf
.Mid(pos
+ 10).BeforeFirst(buf
[(size_t)pos
+9]);
158 pos
= buf
.Find(wxT("version="));
159 if (pos
!= wxNOT_FOUND
)
160 ctx
->version
= buf
.Mid(pos
+ 9).BeforeFirst(buf
[(size_t)pos
+8]);
164 bool wxXmlIOHandlerExpat::Load(wxInputStream
& stream
, wxXmlDocument
& doc
)
166 const size_t BUFSIZE
= 1024;
168 wxXmlParsingContext ctx
;
170 XML_Parser parser
= XML_ParserCreate(NULL
);
172 ctx
.root
= ctx
.node
= NULL
;
173 XML_SetUserData(parser
, (void*)&ctx
);
174 XML_SetElementHandler(parser
, StartElementHnd
, EndElementHnd
);
175 XML_SetCharacterDataHandler(parser
, TextHnd
);
176 XML_SetCommentHandler(parser
, CommentHnd
);
177 XML_SetDefaultHandler(parser
, DefaultHnd
);
181 size_t len
= stream
.Read(buf
, BUFSIZE
).LastRead();
182 done
= (len
< BUFSIZE
);
183 if (!XML_Parse(parser
, buf
, len
, done
))
185 wxLogError(_("XML parsing error: '%s' at line %d"),
186 XML_ErrorString(XML_GetErrorCode(parser
)),
187 XML_GetCurrentLineNumber(parser
));
192 doc
.SetVersion(ctx
.version
);
193 doc
.SetEncoding(ctx
.encoding
);
194 doc
.SetRoot(ctx
.root
);
196 XML_ParserFree(parser
);