X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/fa6a837300efb9d295b889a8308b74537c9d8677..0cebbfc2bd3a22ee50f789fca623d9037660e495:/src/xml/xml.cpp?ds=sidebyside diff --git a/src/xml/xml.cpp b/src/xml/xml.cpp index 067cd02319..6a76beb7c6 100644 --- a/src/xml/xml.cpp +++ b/src/xml/xml.cpp @@ -39,6 +39,9 @@ WX_CHECK_BUILD_OPTIONS("wxXML") IMPLEMENT_CLASS(wxXmlDocument, wxObject) +// a private utility used by wxXML +static bool wxIsWhiteOnly(const wxChar *buf); + //----------------------------------------------------------------------------- // wxXmlNode @@ -309,6 +312,28 @@ wxString wxXmlNode::GetNodeContent() const return wxEmptyString; } +int wxXmlNode::GetDepth(wxXmlNode *grandparent) const +{ + const wxXmlNode *n = this; + int ret = -1; + + do + { + ret++; + n = n->GetParent(); + if (n == grandparent) + return ret; + + } while (n); + + return wxNOT_FOUND; +} + +bool wxXmlNode::IsWhitespaceOnly() const +{ + return wxIsWhiteOnly(m_content); +} + //----------------------------------------------------------------------------- @@ -364,20 +389,20 @@ void wxXmlDocument::DoCopy(const wxXmlDocument& doc) m_root = new wxXmlNode(*doc.m_root); } -bool wxXmlDocument::Load(const wxString& filename, const wxString& encoding) +bool wxXmlDocument::Load(const wxString& filename, const wxString& encoding, int flags) { wxFileInputStream stream(filename); if (!stream.Ok()) return false; - return Load(stream, encoding); + return Load(stream, encoding, flags); } -bool wxXmlDocument::Save(const wxString& filename) const +bool wxXmlDocument::Save(const wxString& filename, int indentstep) const { wxFileOutputStream stream(filename); if (!stream.Ok()) return false; - return Save(stream); + return Save(stream, indentstep); } @@ -386,11 +411,6 @@ bool wxXmlDocument::Save(const wxString& filename) const // wxXmlDocument loading routines //----------------------------------------------------------------------------- -/* - FIXME: - - process all elements, including CDATA - */ - // converts Expat-produced string in UTF-8 into wxString using the specified // conv or keep in UTF-8 if conv is NULL static wxString CharToString(wxMBConv *conv, @@ -417,6 +437,16 @@ static wxString CharToString(wxMBConv *conv, #endif // wxUSE_UNICODE/!wxUSE_UNICODE } +// returns true if the given string contains only whitespaces +bool wxIsWhiteOnly(const wxChar *buf) +{ + for (const wxChar *c = buf; *c != wxT('\0'); c++) + if (*c != wxT(' ') && *c != wxT('\t') && *c != wxT('\n') && *c != wxT('\r')) + return false; + return true; +} + + struct wxXmlParsingContext { wxMBConv *conv; @@ -425,7 +455,8 @@ struct wxXmlParsingContext wxXmlNode *lastAsText; wxString encoding; wxString version; - bool bLastCdata; + bool bLastCdata; + bool removeWhiteOnlyNodes; }; extern "C" { @@ -462,42 +493,32 @@ extern "C" { 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); + wxString str = CharToString(ctx->conv, s, len); if (ctx->lastAsText) { - if ( ctx->bLastCdata ) - { - ctx->lastAsText->SetContent(ctx->lastAsText->GetContent() + - CharToString(NULL, buf)); - } - else - { - ctx->lastAsText->SetContent(ctx->lastAsText->GetContent() + - CharToString(ctx->conv, buf)); - } + if ( ctx->bLastCdata ) + { + ctx->lastAsText->SetContent(ctx->lastAsText->GetContent() + + CharToString(NULL, s, len)); + } + else + { + ctx->lastAsText->SetContent(ctx->lastAsText->GetContent() + str); + } } else { - bool whiteOnly = true; - for (char *c = buf; *c != '\0'; c++) - if (*c != ' ' && *c != '\t' && *c != '\n' && *c != '\r') - { - whiteOnly = false; - break; - } + bool whiteOnly = false; + if (ctx->removeWhiteOnlyNodes) + whiteOnly = wxIsWhiteOnly(str); + if (!whiteOnly) { - ctx->lastAsText = new wxXmlNode(wxXML_TEXT_NODE, wxT("text"), - CharToString(ctx->conv, buf)); + ctx->lastAsText = new wxXmlNode(wxXML_TEXT_NODE, wxT("text"), str); ctx->node->AddChild(ctx->lastAsText); } } - - delete[] buf; } } @@ -506,10 +527,10 @@ static void StartCdataHnd(void *userData) { wxXmlParsingContext *ctx = (wxXmlParsingContext*)userData; - ctx->bLastCdata = true; - - ctx->lastAsText = new wxXmlNode(wxXML_CDATA_SECTION_NODE, wxT("cdata"),wxT("")); - ctx->node->AddChild(ctx->lastAsText); + ctx->bLastCdata = true; + + ctx->lastAsText = new wxXmlNode(wxXML_CDATA_SECTION_NODE, wxT("cdata"),wxT("")); + ctx->node->AddChild(ctx->lastAsText); } } @@ -518,7 +539,7 @@ static void EndCdataHnd(void *userData) { wxXmlParsingContext *ctx = (wxXmlParsingContext*)userData; - ctx->bLastCdata = false; + ctx->bLastCdata = false; } } @@ -593,7 +614,7 @@ static int UnknownEncodingHnd(void * WXUNUSED(encodingHandlerData), } } -bool wxXmlDocument::Load(wxInputStream& stream, const wxString& encoding) +bool wxXmlDocument::Load(wxInputStream& stream, const wxString& encoding, int flags) { #if wxUSE_UNICODE (void)encoding; @@ -614,12 +635,13 @@ bool wxXmlDocument::Load(wxInputStream& stream, const wxString& encoding) if ( encoding != wxT("UTF-8") && encoding != wxT("utf-8") ) ctx.conv = new wxCSConv(encoding); #endif - ctx.bLastCdata = false; + ctx.removeWhiteOnlyNodes = (flags & wxXMLDOC_KEEP_WHITESPACE_NODES) == 0; + ctx.bLastCdata = false; XML_SetUserData(parser, (void*)&ctx); XML_SetElementHandler(parser, StartElementHnd, EndElementHnd); XML_SetCharacterDataHandler(parser, TextHnd); - XML_SetCdataSectionHandler(parser, StartCdataHnd, EndCdataHnd ); + XML_SetCdataSectionHandler(parser, StartCdataHnd, EndCdataHnd ); XML_SetCommentHandler(parser, CommentHnd); XML_SetDefaultHandler(parser, DefaultHnd); XML_SetUnknownEncodingHandler(parser, UnknownEncodingHnd, NULL); @@ -755,18 +777,18 @@ inline static void OutputIndentation(wxOutputStream& stream, int indent) } static void OutputNode(wxOutputStream& stream, wxXmlNode *node, int indent, - wxMBConv *convMem, wxMBConv *convFile) + wxMBConv *convMem, wxMBConv *convFile, int indentstep) { wxXmlNode *n, *prev; wxXmlProperty *prop; switch (node->GetType()) { - case wxXML_CDATA_SECTION_NODE: - OutputString( stream, wxT("GetContent() ); - OutputString( stream, wxT("]]>") ); - break; + case wxXML_CDATA_SECTION_NODE: + OutputString( stream, wxT("GetContent() ); + OutputString( stream, wxT("]]>") ); + break; case wxXML_TEXT_NODE: OutputStringEnt(stream, node->GetContent(), convMem, convFile); @@ -793,13 +815,13 @@ static void OutputNode(wxOutputStream& stream, wxXmlNode *node, int indent, n = node->GetChildren(); while (n) { - if (n && n->GetType() != wxXML_TEXT_NODE) - OutputIndentation(stream, indent + 1); - OutputNode(stream, n, indent + 1, convMem, convFile); + if (indentstep >= 0 && n && n->GetType() != wxXML_TEXT_NODE) + OutputIndentation(stream, indent + indentstep); + OutputNode(stream, n, indent + indentstep, convMem, convFile, indentstep); prev = n; n = n->GetNext(); } - if (prev && prev->GetType() != wxXML_TEXT_NODE) + if (indentstep >= 0 && prev && prev->GetType() != wxXML_TEXT_NODE) OutputIndentation(stream, indent); OutputString(stream, wxT("GetName()); @@ -820,7 +842,7 @@ static void OutputNode(wxOutputStream& stream, wxXmlNode *node, int indent, } } -bool wxXmlDocument::Save(wxOutputStream& stream) const +bool wxXmlDocument::Save(wxOutputStream& stream, int indentstep) const { if ( !IsOk() ) return false; @@ -844,7 +866,7 @@ bool wxXmlDocument::Save(wxOutputStream& stream) const GetVersion().c_str(), GetFileEncoding().c_str()); OutputString(stream, s); - OutputNode(stream, GetRoot(), 0, convMem, convFile); + OutputNode(stream, GetRoot(), 0, convMem, convFile, indentstep); OutputString(stream, wxT("\n")); if ( convFile )