]>
git.saurik.com Git - wxWidgets.git/blob - src/xrc/xmlexpat.cpp
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"
33 - process all elements, including CDATA
38 // converts Expat-produced string in UTF-8 into wxString.
39 inline static wxString
CharToString(wxMBConv
*conv
,
40 const char *s
, size_t len
= wxSTRING_MAXLEN
)
44 return wxString(s
, wxConvUTF8
, len
);
48 size_t nLen
= (len
!= wxSTRING_MAXLEN
) ? len
:
49 nLen
= wxConvUTF8
.MB2WC((wchar_t*) NULL
, s
, 0);
51 wchar_t *buf
= new wchar_t[nLen
+1];
52 wxConvUTF8
.MB2WC(buf
, s
, nLen
);
54 return wxString(buf
, *conv
, len
);
58 return wxString(s
, len
);
62 bool wxXmlIOHandlerExpat::CanLoad(wxInputStream
& stream
)
66 stream
.Read(cheader
, 6);
67 stream
.SeekI(-6, wxFromCurrent
);
68 return (strcmp(cheader
, "<?xml ") == 0);
72 struct wxXmlParsingContext
78 wxXmlNode
*lastAsText
;
83 static void StartElementHnd(void *userData
, const char *name
, const char **atts
)
85 wxXmlParsingContext
*ctx
= (wxXmlParsingContext
*)userData
;
86 wxXmlNode
*node
= new wxXmlNode(wxXML_ELEMENT_NODE
, CharToString(ctx
->conv
, name
));
87 const char **a
= atts
;
90 node
->AddProperty(CharToString(ctx
->conv
, a
[0]), CharToString(ctx
->conv
, a
[1]));
93 if (ctx
->root
== NULL
)
96 ctx
->node
->AddChild(node
);
98 ctx
->lastAsText
= NULL
;
101 static void EndElementHnd(void *userData
, const char* WXUNUSED(name
))
103 wxXmlParsingContext
*ctx
= (wxXmlParsingContext
*)userData
;
105 ctx
->node
= ctx
->node
->GetParent();
106 ctx
->lastAsText
= NULL
;
109 static void TextHnd(void *userData
, const char *s
, int len
)
111 wxXmlParsingContext
*ctx
= (wxXmlParsingContext
*)userData
;
112 char *buf
= new char[len
+ 1];
115 memcpy(buf
, s
, (size_t)len
);
119 ctx
->lastAsText
->SetContent(ctx
->lastAsText
->GetContent() +
120 CharToString(ctx
->conv
, buf
));
124 bool whiteOnly
= TRUE
;
125 for (char *c
= buf
; *c
!= '\0'; c
++)
126 if (*c
!= ' ' && *c
!= '\t' && *c
!= '\n' && *c
!= '\r')
133 ctx
->lastAsText
= new wxXmlNode(wxXML_TEXT_NODE
, wxT("text"),
134 CharToString(ctx
->conv
, buf
));
135 ctx
->node
->AddChild(ctx
->lastAsText
);
142 static void CommentHnd(void *userData
, const char *data
)
144 wxXmlParsingContext
*ctx
= (wxXmlParsingContext
*)userData
;
148 // VS: ctx->node == NULL happens if there is a comment before
149 // the root element (e.g. wxDesigner's output). We ignore such
150 // comments, no big deal...
151 ctx
->node
->AddChild(new wxXmlNode(wxXML_COMMENT_NODE
,
152 wxT("comment"), CharToString(ctx
->conv
, data
)));
154 ctx
->lastAsText
= NULL
;
157 static void DefaultHnd(void *userData
, const char *s
, int len
)
160 if (len
> 6 && memcmp(s
, "<?xml ", 6) == 0)
162 wxXmlParsingContext
*ctx
= (wxXmlParsingContext
*)userData
;
164 wxString buf
= CharToString(ctx
->conv
, s
, (size_t)len
);
166 pos
= buf
.Find(wxT("encoding="));
167 if (pos
!= wxNOT_FOUND
)
168 ctx
->encoding
= buf
.Mid(pos
+ 10).BeforeFirst(buf
[(size_t)pos
+9]);
169 pos
= buf
.Find(wxT("version="));
170 if (pos
!= wxNOT_FOUND
)
171 ctx
->version
= buf
.Mid(pos
+ 9).BeforeFirst(buf
[(size_t)pos
+8]);
175 static int UnknownEncodingHnd(void * WXUNUSED(encodingHandlerData
),
176 const XML_Char
*name
, XML_Encoding
*info
)
178 // We must build conversion table for expat. The easiest way to do so
179 // is to let wxCSConv convert as string containing all characters to
180 // wide character representation:
186 for (i
= 0; i
< 255; i
++)
189 conv
.MB2WC(wcBuf
, mbBuf
, 255);
193 for (i
= 0; i
< 255; i
++)
194 info
->map
[i
+1] = (int)wcBuf
[i
];
197 info
->convert
= NULL
;
198 info
->release
= NULL
;
203 bool wxXmlIOHandlerExpat::Load(wxInputStream
& stream
, wxXmlDocument
& doc
,
204 const wxString
& encoding
)
206 const size_t BUFSIZE
= 1024;
208 wxXmlParsingContext ctx
;
210 XML_Parser parser
= XML_ParserCreate(NULL
);
212 ctx
.root
= ctx
.node
= NULL
;
213 ctx
.encoding
= wxT("UTF-8"); // default in absence of encoding=""
216 if ( encoding
!= wxT("UTF-8") && encoding
!= wxT("utf-8") )
217 ctx
.conv
= new wxCSConv(encoding
);
220 XML_SetUserData(parser
, (void*)&ctx
);
221 XML_SetElementHandler(parser
, StartElementHnd
, EndElementHnd
);
222 XML_SetCharacterDataHandler(parser
, TextHnd
);
223 XML_SetCommentHandler(parser
, CommentHnd
);
224 XML_SetDefaultHandler(parser
, DefaultHnd
);
225 XML_SetUnknownEncodingHandler(parser
, UnknownEncodingHnd
, NULL
);
229 size_t len
= stream
.Read(buf
, BUFSIZE
).LastRead();
230 done
= (len
< BUFSIZE
);
231 if (!XML_Parse(parser
, buf
, len
, done
))
233 wxLogError(_("XML parsing error: '%s' at line %d"),
234 XML_ErrorString(XML_GetErrorCode(parser
)),
235 XML_GetCurrentLineNumber(parser
));
240 doc
.SetVersion(ctx
.version
);
241 doc
.SetFileEncoding(ctx
.encoding
);
242 doc
.SetRoot(ctx
.root
);
244 XML_ParserFree(parser
);