]>
git.saurik.com Git - wxWidgets.git/blob - contrib/src/xml/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/xml/xmlio.h"
34 - handle unknown encodings
35 - process all elements, including CDATA
36 - XML resources should automatically select desired encoding besed 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
, wxMBConvUTF8
, 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 *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
;
135 ctx
->node
->AddChild(new wxXmlNode(wxXML_COMMENT_NODE
,
136 wxT("comment"), CharToString(data
)));
137 ctx
->lastAsText
= NULL
;
140 static void DefaultHnd(void *userData
, const char *s
, int len
)
143 if (len
> 6 && memcmp(s
, "<?xml ", 6) == 0)
145 wxXmlParsingContext
*ctx
= (wxXmlParsingContext
*)userData
;
147 wxString buf
= CharToString(s
, (size_t)len
);
149 pos
= buf
.Find(wxT("encoding="));
150 if (pos
!= wxNOT_FOUND
)
151 ctx
->encoding
= buf
.Mid(pos
+ 10).BeforeFirst(buf
[(size_t)pos
+9]);
152 pos
= buf
.Find(wxT("version="));
153 if (pos
!= wxNOT_FOUND
)
154 ctx
->version
= buf
.Mid(pos
+ 9).BeforeFirst(buf
[(size_t)pos
+8]);
158 bool wxXmlIOHandlerExpat::Load(wxInputStream
& stream
, wxXmlDocument
& doc
)
160 const size_t BUFSIZE
= 1024;
162 wxXmlParsingContext ctx
;
164 XML_Parser parser
= XML_ParserCreate(NULL
);
166 ctx
.root
= ctx
.node
= NULL
;
167 XML_SetUserData(parser
, (void*)&ctx
);
168 XML_SetElementHandler(parser
, StartElementHnd
, EndElementHnd
);
169 XML_SetCharacterDataHandler(parser
, TextHnd
);
170 XML_SetCommentHandler(parser
, CommentHnd
);
171 XML_SetDefaultHandler(parser
, DefaultHnd
);
175 size_t len
= stream
.Read(buf
, BUFSIZE
).LastRead();
176 done
= (len
< BUFSIZE
);
177 if (!XML_Parse(parser
, buf
, len
, done
))
179 wxLogError(_("XML parsing error: '%s' at line %d"),
180 XML_ErrorString(XML_GetErrorCode(parser
)),
181 XML_GetCurrentLineNumber(parser
));
186 doc
.SetVersion(ctx
.version
);
187 doc
.SetEncoding(ctx
.encoding
);
188 doc
.SetRoot(ctx
.root
);
190 XML_ParserFree(parser
);