update XMLStorage: preserve CDATA formating of processed XML documents

svn path=/trunk/; revision=38492
This commit is contained in:
Martin Fuchs 2008-12-31 15:59:36 +00:00
parent ee252ea491
commit 607be3272e
3 changed files with 68 additions and 28 deletions

View file

@ -471,9 +471,16 @@ std::string EncodeXMLString(const XS_String& str, bool cdata)
} }
/// decode XML string literals /// 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 buffer = (LPXSSTR)alloca(sizeof(XS_CHAR)*XS_len(s));
LPXSSTR o = buffer; 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 /// 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); out << _leading << '<' << EncodeXMLString(*this);
@ -522,10 +529,15 @@ void XMLNode::write_worker(std::ostream& out) const
out << ' ' << EncodeXMLString(it->first) << "=\"" << EncodeXMLString(it->second) << "\""; out << ' ' << EncodeXMLString(it->first) << "=\"" << EncodeXMLString(it->second) << "\"";
if (!_children.empty() || !_content.empty()) { 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) for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it)
(*it)->write_worker(out); (*it)->original_write_worker(out);
out << _end_leading << "</" << EncodeXMLString(*this) << '>'; out << _end_leading << "</" << EncodeXMLString(*this) << '>';
} else } else
@ -619,7 +631,9 @@ void XMLNode::smart_write_worker(std::ostream& out, const XMLFormat& format, int
else { else {
out << '>'; out << '>';
if (!*content) if (_cdata_content)
out << EncodeXMLString(DecodeXMLString(_content), true);
else if (!*content)
out << format._endl; out << format._endl;
else else
out << content; out << content;
@ -886,11 +900,15 @@ void XMLReaderBase::EndElementHandler()
if (!strncmp(s,"<![CDATA[",9) && !strncmp(e-3,"]]>",3)) { if (!strncmp(s,"<![CDATA[",9) && !strncmp(e-3,"]]>",3)) {
s += 9; s += 9;
p = (e-=3); p = (e-=3);
_pos->_cdata_content = true;
} else { } else {
// search for content end leaving only white space for _end_leading // search for content end leaving only white space for _end_leading
for(p=e; p>s; --p) for(p=e; p>s; --p)
if (!isspace((unsigned char)p[-1])) if (!isspace((unsigned char)p[-1]))
break; break;
_pos->_cdata_content = false;
} }
if (p != s) if (p != s)

View file

@ -484,7 +484,7 @@ inline std::string get_utf8(const XS_String& s)
#endif // XS_STRING_UTF8 #endif // XS_STRING_UTF8
extern std::string EncodeXMLString(const XS_String& str, bool cdata=false); 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__ #ifdef __GNUC__
@ -961,13 +961,15 @@ struct XMLNode : public XS_String
friend struct XPathElement; friend struct XPathElement;
XMLNode(const XS_String& name) XMLNode(const XS_String& name)
: XS_String(name) : XS_String(name),
_cdata_content(false)
{ {
} }
XMLNode(const XS_String& name, const std::string& leading) XMLNode(const XS_String& name, const std::string& leading)
: XS_String(name), : XS_String(name),
_leading(leading) _leading(leading),
_cdata_content(false)
{ {
} }
@ -977,10 +979,11 @@ struct XMLNode : public XS_String
_leading(other._leading), _leading(other._leading),
_content(other._content), _content(other._content),
_end_leading(other._end_leading), _end_leading(other._end_leading),
_trailing(other._trailing) _trailing(other._trailing),
#ifdef XMLNODE_LOCATION #ifdef XMLNODE_LOCATION
, _location(other._location) _location(other._location),
#endif #endif
_cdata_content(false)
{ {
for(Children::const_iterator it=other._children.begin(); it!=other._children.end(); ++it) for(Children::const_iterator it=other._children.begin(); it!=other._children.end(); ++it)
_children.push_back(new XMLNode(**it)); _children.push_back(new XMLNode(**it));
@ -994,10 +997,11 @@ struct XMLNode : public XS_String
_leading(other._leading), _leading(other._leading),
_content(other._content), _content(other._content),
_end_leading(other._end_leading), _end_leading(other._end_leading),
_trailing(other._trailing) _trailing(other._trailing),
#ifdef XMLNODE_LOCATION #ifdef XMLNODE_LOCATION
, _location(other._location) _location(other._location),
#endif #endif
_cdata_content(false)
{ {
// assert(copy_no_children==COPY_NOCHILDREN); // assert(copy_no_children==COPY_NOCHILDREN);
} }
@ -1153,23 +1157,41 @@ struct XMLNode : public XS_String
return _attributes; return _attributes;
} }
/// read element node content
XS_String get_content() const XS_String get_content() const
{ {
#ifdef XS_STRING_UTF8 return DecodeXMLString(_content);
const XS_String& ret = _content;
#else
XS_String ret;
assign_utf8(ret, _content.c_str(), _content.length());
#endif
return DecodeXMLString(ret.c_str());
} }
/// 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) void set_content(const XS_String& s, bool cdata=false)
{ {
_content.assign(EncodeXMLString(s.c_str(), cdata)); _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 #ifdef XMLNODE_LOCATION
const XMLLocation& get_location() const {return _location;} const XMLLocation& get_location() const {return _location;}
#endif #endif
@ -1187,10 +1209,10 @@ struct XMLNode : public XS_String
break; break;
case FORMAT_ORIGINAL: case FORMAT_ORIGINAL:
write_worker(out); original_write_worker(out);
break; break;
default: // FORMAT_SMART default: // FORMAT_SMART
smart_write_worker(out, format, indent); smart_write_worker(out, format, indent);
} }
@ -1222,6 +1244,8 @@ protected:
XMLLocation _location; XMLLocation _location;
#endif #endif
bool _cdata_content;
XMLNode* get_first_child() const XMLNode* get_first_child() const
{ {
if (!_children.empty()) if (!_children.empty())
@ -1242,7 +1266,7 @@ protected:
/// create a new node tree using the given XPath filter expression /// create a new node tree using the given XPath filter expression
XMLNode* filter(XPath::const_iterator from, const XPath::const_iterator& to) const; 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 plain_write_worker(std::ostream& out) const;
void pretty_write_worker(std::ostream& out, const XMLFormat& format, int indent) 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; void smart_write_worker(std::ostream& out, const XMLFormat& format, int indent) const;

View file

@ -206,14 +206,12 @@ struct Buffer
#ifdef XS_STRING_UTF8 #ifdef XS_STRING_UTF8
XS_String name_str(attr_name, attr_len); XS_String name_str(attr_name, attr_len);
XS_String value_str(value, value_len);
#else #else
XS_String name_str, value_str; XS_String name_str;
assign_utf8(name_str, attr_name, attr_len); assign_utf8(name_str, attr_name, attr_len);
assign_utf8(value_str, value, value_len);
#endif #endif
attributes[name_str] = DecodeXMLString(value_str); attributes[name_str] = DecodeXMLString(std::string(value, value_len));
} }
} }