📄 xml.cpp
字号:
{ wxMBConv *conv; wxXmlNode *root; wxXmlNode *node; wxXmlNode *lastAsText; wxString encoding; wxString version;};static void StartElementHnd(void *userData, const char *name, const char **atts){ wxXmlParsingContext *ctx = (wxXmlParsingContext*)userData; wxXmlNode *node = new wxXmlNode(wxXML_ELEMENT_NODE, CharToString(ctx->conv, name)); const char **a = atts; while (*a) { node->AddProperty(CharToString(ctx->conv, a[0]), CharToString(ctx->conv, a[1])); a += 2; } if (ctx->root == NULL) ctx->root = node; else ctx->node->AddChild(node); ctx->node = node; ctx->lastAsText = NULL;}static void EndElementHnd(void *userData, const char* WXUNUSED(name)){ wxXmlParsingContext *ctx = (wxXmlParsingContext*)userData; ctx->node = ctx->node->GetParent(); ctx->lastAsText = NULL;}static void TextHnd(void *userData, const char *s, int len){ wxXmlParsingContext *ctx = (wxXmlParsingContext*)userData; char *buf = new char[len + 1]; buf[len] = '\0'; memcpy(buf, s, (size_t)len); if (ctx->lastAsText) { ctx->lastAsText->SetContent(ctx->lastAsText->GetContent() + CharToString(ctx->conv, buf)); } else { bool whiteOnly = TRUE; for (char *c = buf; *c != '\0'; c++) if (*c != ' ' && *c != '\t' && *c != '\n' && *c != '\r') { whiteOnly = FALSE; break; } if (!whiteOnly) { ctx->lastAsText = new wxXmlNode(wxXML_TEXT_NODE, wxT("text"), CharToString(ctx->conv, buf)); ctx->node->AddChild(ctx->lastAsText); } } delete[] buf;}static void CommentHnd(void *userData, const char *data){ wxXmlParsingContext *ctx = (wxXmlParsingContext*)userData; if (ctx->node) { // VS: ctx->node == NULL happens if there is a comment before // the root element (e.g. wxDesigner's output). We ignore such // comments, no big deal... ctx->node->AddChild(new wxXmlNode(wxXML_COMMENT_NODE, wxT("comment"), CharToString(ctx->conv, data))); } ctx->lastAsText = NULL;}static void DefaultHnd(void *userData, const char *s, int len){ // XML header: if (len > 6 && memcmp(s, "<?xml ", 6) == 0) { wxXmlParsingContext *ctx = (wxXmlParsingContext*)userData; wxString buf = CharToString(ctx->conv, s, (size_t)len); int pos; pos = buf.Find(wxT("encoding=")); if (pos != wxNOT_FOUND) ctx->encoding = buf.Mid(pos + 10).BeforeFirst(buf[(size_t)pos+9]); pos = buf.Find(wxT("version=")); if (pos != wxNOT_FOUND) ctx->version = buf.Mid(pos + 9).BeforeFirst(buf[(size_t)pos+8]); }}static int UnknownEncodingHnd(void * WXUNUSED(encodingHandlerData), const XML_Char *name, XML_Encoding *info){ // We must build conversion table for expat. The easiest way to do so // is to let wxCSConv convert as string containing all characters to // wide character representation: wxCSConv conv(wxString(name, wxConvLibc)); char mbBuf[2]; wchar_t wcBuf[10]; size_t i; mbBuf[1] = 0; info->map[0] = 0; for (i = 0; i < 255; i++) { mbBuf[0] = (char)(i+1); if (conv.MB2WC(wcBuf, mbBuf, 2) == (size_t)-1) { // invalid/undefined byte in the encoding: info->map[i+1] = -1; } info->map[i+1] = (int)wcBuf[0]; } info->data = NULL; info->convert = NULL; info->release = NULL; return 1;}bool wxXmlDocument::Load(wxInputStream& stream, const wxString& encoding){#if wxUSE_UNICODE (void)encoding;#else m_encoding = encoding;#endif const size_t BUFSIZE = 1024; char buf[BUFSIZE]; wxXmlParsingContext ctx; bool done; XML_Parser parser = XML_ParserCreate(NULL); ctx.root = ctx.node = NULL; ctx.encoding = wxT("UTF-8"); // default in absence of encoding="" ctx.conv = NULL;#if !wxUSE_UNICODE if ( encoding != wxT("UTF-8") && encoding != wxT("utf-8") ) ctx.conv = new wxCSConv(encoding);#endif XML_SetUserData(parser, (void*)&ctx); XML_SetElementHandler(parser, StartElementHnd, EndElementHnd); XML_SetCharacterDataHandler(parser, TextHnd); XML_SetCommentHandler(parser, CommentHnd); XML_SetDefaultHandler(parser, DefaultHnd); XML_SetUnknownEncodingHandler(parser, UnknownEncodingHnd, NULL); bool ok = true; do { size_t len = stream.Read(buf, BUFSIZE).LastRead(); done = (len < BUFSIZE); if (!XML_Parse(parser, buf, len, done)) { wxString error(XML_ErrorString(XML_GetErrorCode(parser)), *wxConvCurrent); wxLogError(_("XML parsing error: '%s' at line %d"), error.c_str(), XML_GetCurrentLineNumber(parser)); ok = false; break; } } while (!done); if (ok) { if (!ctx.version.IsEmpty()) SetVersion(ctx.version); if (!ctx.encoding.IsEmpty()) SetFileEncoding(ctx.encoding); SetRoot(ctx.root); } else { delete ctx.root; } XML_ParserFree(parser);#if !wxUSE_UNICODE if ( ctx.conv ) delete ctx.conv;#endif return ok;}//-----------------------------------------------------------------------------// wxXmlDocument saving routines//-----------------------------------------------------------------------------// write string to output:inline static void OutputString(wxOutputStream& stream, const wxString& str,#if wxUSE_UNICODE wxMBConv * WXUNUSED(convMem),#else wxMBConv *convMem,#endif wxMBConv *convFile){ if (str.IsEmpty()) return;#if wxUSE_UNICODE const wxWX2MBbuf buf(str.mb_str(*(convFile ? convFile : &wxConvUTF8))); stream.Write((const char*)buf, strlen((const char*)buf));#else if ( convFile == NULL ) stream.Write(str.mb_str(), str.Len()); else { wxString str2(str.wc_str(*convMem), *convFile); stream.Write(str2.mb_str(), str2.Len()); }#endif}// Same as above, but create entities first.// Translates '<' to "<", '>' to ">" and '&' to "&"static void OutputStringEnt(wxOutputStream& stream, const wxString& str, wxMBConv *convMem, wxMBConv *convFile, bool escapeQuotes = false){ wxString buf; size_t i, last, len; wxChar c; len = str.Len(); last = 0; for (i = 0; i < len; i++) { c = str.GetChar(i); if (c == wxT('<') || c == wxT('>') || (c == wxT('&') && str.Mid(i+1, 4) != wxT("amp;")) || (escapeQuotes && c == wxT('"'))) { OutputString(stream, str.Mid(last, i - last), convMem, convFile); switch (c) { case wxT('<'): OutputString(stream, wxT("<"), NULL, NULL); break; case wxT('>'): OutputString(stream, wxT(">"), NULL, NULL); break; case wxT('&'): OutputString(stream, wxT("&"), NULL, NULL); break; case wxT('"'): OutputString(stream, wxT("""), NULL, NULL); break; default: break; } last = i + 1; } } OutputString(stream, str.Mid(last, i - last), convMem, convFile);}inline static void OutputIndentation(wxOutputStream& stream, int indent){ wxString str = wxT("\n"); for (int i = 0; i < indent; i++) str << wxT(' ') << wxT(' '); OutputString(stream, str, NULL, NULL);}static void OutputNode(wxOutputStream& stream, wxXmlNode *node, int indent, wxMBConv *convMem, wxMBConv *convFile){ wxXmlNode *n, *prev; wxXmlProperty *prop; switch (node->GetType()) { case wxXML_TEXT_NODE: OutputStringEnt(stream, node->GetContent(), convMem, convFile); break; case wxXML_ELEMENT_NODE: OutputString(stream, wxT("<"), NULL, NULL); OutputString(stream, node->GetName(), NULL, NULL); prop = node->GetProperties(); while (prop) { OutputString(stream, wxT(" ") + prop->GetName() + wxT("=\""), NULL, NULL); OutputStringEnt(stream, prop->GetValue(), NULL, NULL, true/*escapeQuotes*/); OutputString(stream, wxT("\""), NULL, NULL); prop = prop->GetNext(); } if (node->GetChildren()) { OutputString(stream, wxT(">"), NULL, NULL); prev = NULL; n = node->GetChildren(); while (n) { if (n && n->GetType() != wxXML_TEXT_NODE) OutputIndentation(stream, indent + 1); OutputNode(stream, n, indent + 1, convMem, convFile); prev = n; n = n->GetNext(); } if (prev && prev->GetType() != wxXML_TEXT_NODE) OutputIndentation(stream, indent); OutputString(stream, wxT("</"), NULL, NULL); OutputString(stream, node->GetName(), NULL, NULL); OutputString(stream, wxT(">"), NULL, NULL); } else OutputString(stream, wxT("/>"), NULL, NULL); break; case wxXML_COMMENT_NODE: OutputString(stream, wxT("<!--"), NULL, NULL); OutputString(stream, node->GetContent(), convMem, convFile); OutputString(stream, wxT("-->"), NULL, NULL); break; default: wxFAIL_MSG(wxT("unsupported node type")); }}bool wxXmlDocument::Save(wxOutputStream& stream) const{ if ( !IsOk() ) return FALSE; wxString s; wxMBConv *convMem = NULL, *convFile = NULL;#if wxUSE_UNICODE convFile = new wxCSConv(GetFileEncoding());#else if ( GetFileEncoding() != GetEncoding() ) { convFile = new wxCSConv(GetFileEncoding()); convMem = new wxCSConv(GetEncoding()); }#endif s.Printf(wxT("<?xml version=\"%s\" encoding=\"%s\"?>\n"), GetVersion().c_str(), GetFileEncoding().c_str()); OutputString(stream, s, NULL, NULL); OutputNode(stream, GetRoot(), 0, convMem, convFile); OutputString(stream, wxT("\n"), NULL, NULL); if ( convFile ) delete convFile; if ( convMem ) delete convMem; return TRUE;}#endif // wxUSE_XML#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -