From 607be3272e233d2702c9278de3efad88e6d01a7f Mon Sep 17 00:00:00 2001 From: Martin Fuchs Date: Wed, 31 Dec 2008 15:59:36 +0000 Subject: [PATCH] update XMLStorage: preserve CDATA formating of processed XML documents svn path=/trunk/; revision=38492 --- .../shell/explorer/utility/xmlstorage.cpp | 30 ++++++++-- .../base/shell/explorer/utility/xmlstorage.h | 60 +++++++++++++------ .../base/shell/explorer/utility/xs-native.cpp | 6 +- 3 files changed, 68 insertions(+), 28 deletions(-) diff --git a/reactos/base/shell/explorer/utility/xmlstorage.cpp b/reactos/base/shell/explorer/utility/xmlstorage.cpp index b1a18ad6c63..eae1d6f585f 100644 --- a/reactos/base/shell/explorer/utility/xmlstorage.cpp +++ b/reactos/base/shell/explorer/utility/xmlstorage.cpp @@ -471,9 +471,16 @@ std::string EncodeXMLString(const XS_String& str, bool cdata) } /// decode XML string literals -XS_String DecodeXMLString(const XS_String& str) +XS_String DecodeXMLString(const std::string& str) { - LPCXSSTR s = str.c_str(); +#ifdef XS_STRING_UTF8 + const XS_String& str_utf8 = str; +#else + XS_String str_utf8; + assign_utf8(str_utf8, str.c_str(), str.length()); +#endif + + LPCXSSTR s = str_utf8.c_str(); LPXSSTR buffer = (LPXSSTR)alloca(sizeof(XS_CHAR)*XS_len(s)); LPXSSTR o = buffer; @@ -514,7 +521,7 @@ XS_String DecodeXMLString(const XS_String& str) /// write node with children tree to output stream using original white space -void XMLNode::write_worker(std::ostream& out) const +void XMLNode::original_write_worker(std::ostream& out) const { out << _leading << '<' << EncodeXMLString(*this); @@ -522,10 +529,15 @@ void XMLNode::write_worker(std::ostream& out) const out << ' ' << EncodeXMLString(it->first) << "=\"" << EncodeXMLString(it->second) << "\""; if (!_children.empty() || !_content.empty()) { - out << '>' << _content; + out << '>'; + + if (_cdata_content) + out << EncodeXMLString(DecodeXMLString(_content), true); + else + out << _content; for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it) - (*it)->write_worker(out); + (*it)->original_write_worker(out); out << _end_leading << "'; } else @@ -619,7 +631,9 @@ void XMLNode::smart_write_worker(std::ostream& out, const XMLFormat& format, int else { out << '>'; - if (!*content) + if (_cdata_content) + out << EncodeXMLString(DecodeXMLString(_content), true); + else if (!*content) out << format._endl; else out << content; @@ -886,11 +900,15 @@ void XMLReaderBase::EndElementHandler() if (!strncmp(s,"",3)) { s += 9; p = (e-=3); + + _pos->_cdata_content = true; } else { // search for content end leaving only white space for _end_leading for(p=e; p>s; --p) if (!isspace((unsigned char)p[-1])) break; + + _pos->_cdata_content = false; } if (p != s) diff --git a/reactos/base/shell/explorer/utility/xmlstorage.h b/reactos/base/shell/explorer/utility/xmlstorage.h index b16ef9093f4..d5d83f27d0c 100644 --- a/reactos/base/shell/explorer/utility/xmlstorage.h +++ b/reactos/base/shell/explorer/utility/xmlstorage.h @@ -484,7 +484,7 @@ inline std::string get_utf8(const XS_String& s) #endif // XS_STRING_UTF8 extern std::string EncodeXMLString(const XS_String& str, bool cdata=false); -extern XS_String DecodeXMLString(const XS_String& str); +extern XS_String DecodeXMLString(const std::string& str); #ifdef __GNUC__ @@ -961,13 +961,15 @@ struct XMLNode : public XS_String friend struct XPathElement; XMLNode(const XS_String& name) - : XS_String(name) + : XS_String(name), + _cdata_content(false) { } XMLNode(const XS_String& name, const std::string& leading) : XS_String(name), - _leading(leading) + _leading(leading), + _cdata_content(false) { } @@ -977,10 +979,11 @@ struct XMLNode : public XS_String _leading(other._leading), _content(other._content), _end_leading(other._end_leading), - _trailing(other._trailing) + _trailing(other._trailing), #ifdef XMLNODE_LOCATION - , _location(other._location) + _location(other._location), #endif + _cdata_content(false) { for(Children::const_iterator it=other._children.begin(); it!=other._children.end(); ++it) _children.push_back(new XMLNode(**it)); @@ -994,10 +997,11 @@ struct XMLNode : public XS_String _leading(other._leading), _content(other._content), _end_leading(other._end_leading), - _trailing(other._trailing) + _trailing(other._trailing), #ifdef XMLNODE_LOCATION - , _location(other._location) + _location(other._location), #endif + _cdata_content(false) { // assert(copy_no_children==COPY_NOCHILDREN); } @@ -1153,23 +1157,41 @@ struct XMLNode : public XS_String return _attributes; } + /// read element node content XS_String get_content() const { -#ifdef XS_STRING_UTF8 - const XS_String& ret = _content; -#else - XS_String ret; - assign_utf8(ret, _content.c_str(), _content.length()); -#endif - - return DecodeXMLString(ret.c_str()); + return DecodeXMLString(_content); } + /// read content of a subnode specified by an XPath expression + XS_String get_sub_content(const XPath& xpath) const + { + const XMLNode* node = find_relative(xpath); + + if (node) + return node->get_content(); + else + return XS_EMPTY_STR; + } + + /// set element node content void set_content(const XS_String& s, bool cdata=false) { _content.assign(EncodeXMLString(s.c_str(), cdata)); } + /// set content of a subnode specified by an XPath expression + bool set_sub_content(const XPath& xpath, const XS_String& s, bool cdata=false) + { + XMLNode* node = find_relative(xpath); + + if (node) { + node->set_content(s, cdata); + return true; + } else + return false; + } + #ifdef XMLNODE_LOCATION const XMLLocation& get_location() const {return _location;} #endif @@ -1187,10 +1209,10 @@ struct XMLNode : public XS_String break; case FORMAT_ORIGINAL: - write_worker(out); + original_write_worker(out); break; - default: // FORMAT_SMART + default: // FORMAT_SMART smart_write_worker(out, format, indent); } @@ -1222,6 +1244,8 @@ protected: XMLLocation _location; #endif + bool _cdata_content; + XMLNode* get_first_child() const { if (!_children.empty()) @@ -1242,7 +1266,7 @@ protected: /// create a new node tree using the given XPath filter expression XMLNode* filter(XPath::const_iterator from, const XPath::const_iterator& to) const; - void write_worker(std::ostream& out) const; + void original_write_worker(std::ostream& out) const; void plain_write_worker(std::ostream& out) const; void pretty_write_worker(std::ostream& out, const XMLFormat& format, int indent) const; void smart_write_worker(std::ostream& out, const XMLFormat& format, int indent) const; diff --git a/reactos/base/shell/explorer/utility/xs-native.cpp b/reactos/base/shell/explorer/utility/xs-native.cpp index 7f56dd2813c..3b19171a565 100644 --- a/reactos/base/shell/explorer/utility/xs-native.cpp +++ b/reactos/base/shell/explorer/utility/xs-native.cpp @@ -206,14 +206,12 @@ struct Buffer #ifdef XS_STRING_UTF8 XS_String name_str(attr_name, attr_len); - XS_String value_str(value, value_len); #else - XS_String name_str, value_str; + XS_String name_str; assign_utf8(name_str, attr_name, attr_len); - assign_utf8(value_str, value, value_len); #endif - attributes[name_str] = DecodeXMLString(value_str); + attributes[name_str] = DecodeXMLString(std::string(value, value_len)); } }