mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 16:32:59 +00:00
update to XMLStorage version 1.3
svn path=/trunk/; revision=33226
This commit is contained in:
parent
6b7e77bfc9
commit
5cfce75c9a
3 changed files with 731 additions and 313 deletions
|
@ -1,8 +1,8 @@
|
||||||
|
|
||||||
//
|
//
|
||||||
// XML storage C++ classes version 1.2
|
// XML storage C++ classes version 1.3
|
||||||
//
|
//
|
||||||
// Copyright (c) 2004, 2005, 2006, 2007 Martin Fuchs <martin-fuchs@gmx.net>
|
// Copyright (c) 2004, 2005, 2006, 2007, 2008 Martin Fuchs <martin-fuchs@gmx.net>
|
||||||
//
|
//
|
||||||
|
|
||||||
/// \file xmlstorage.cpp
|
/// \file xmlstorage.cpp
|
||||||
|
@ -57,6 +57,10 @@ const LPCXSSTR XS_INTFMT = XS_INTFMT_STR;
|
||||||
const LPCXSSTR XS_FLOATFMT = XS_FLOATFMT_STR;
|
const LPCXSSTR XS_FLOATFMT = XS_FLOATFMT_STR;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
const XS_String XS_KEY = XS_KEY_STR;
|
||||||
|
const XS_String XS_VALUE = XS_VALUE_STR;
|
||||||
|
const XS_String XS_PROPERTY = XS_PROPERTY_STR;
|
||||||
|
|
||||||
|
|
||||||
/// remove escape characters from zero terminated string
|
/// remove escape characters from zero terminated string
|
||||||
static std::string unescape(const char* s, char b, char e)
|
static std::string unescape(const char* s, char b, char e)
|
||||||
|
@ -105,18 +109,12 @@ inline std::string unescape(const char* s, size_t l)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// move XPath like to position in XML tree
|
/// move to the position defined by xpath in XML tree
|
||||||
bool XMLPos::go(const char* path)
|
bool XMLPos::go(const XPath& xpath)
|
||||||
{
|
{
|
||||||
XMLNode* node = _cur;
|
XMLNode* node = xpath._absolute? _root: _cur;
|
||||||
|
|
||||||
// Is this an absolute path?
|
node = node->find_relative(xpath);
|
||||||
if (*path == '/') {
|
|
||||||
node = _root;
|
|
||||||
++path;
|
|
||||||
}
|
|
||||||
|
|
||||||
node = node->find_relative(path);
|
|
||||||
|
|
||||||
if (node) {
|
if (node) {
|
||||||
go_to(node);
|
go_to(node);
|
||||||
|
@ -125,18 +123,12 @@ bool XMLPos::go(const char* path)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// move XPath like to position in XML tree
|
/// move to the position defined by xpath in XML tree
|
||||||
bool const_XMLPos::go(const char* path)
|
bool const_XMLPos::go(const XPath& xpath)
|
||||||
{
|
{
|
||||||
const XMLNode* node = _cur;
|
const XMLNode* node = xpath._absolute? _root: _cur;
|
||||||
|
|
||||||
// Is this an absolute path?
|
node = node->find_relative(xpath);
|
||||||
if (*path == '/') {
|
|
||||||
node = _root;
|
|
||||||
++path;
|
|
||||||
}
|
|
||||||
|
|
||||||
node = node->find_relative(path);
|
|
||||||
|
|
||||||
if (node) {
|
if (node) {
|
||||||
go_to(node);
|
go_to(node);
|
||||||
|
@ -146,40 +138,7 @@ bool const_XMLPos::go(const char* path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const XMLNode* XMLNode::find_relative(const char* path) const
|
const char* XPathElement::parse(const char* path)
|
||||||
{
|
|
||||||
const XMLNode* node = this;
|
|
||||||
|
|
||||||
// parse relative path
|
|
||||||
while(*path) {
|
|
||||||
node = const_cast<XMLNode*>(node)->get_child_relative(path, false); // get_child_relative() ist const for create==false
|
|
||||||
|
|
||||||
if (!node)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (*path == '/')
|
|
||||||
++path;
|
|
||||||
}
|
|
||||||
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
XMLNode* XMLNode::create_relative(const char* path)
|
|
||||||
{
|
|
||||||
XMLNode* node = this;
|
|
||||||
|
|
||||||
// parse relative path
|
|
||||||
while(*path) {
|
|
||||||
node = node->get_child_relative(path, true);
|
|
||||||
|
|
||||||
if (*path == '/')
|
|
||||||
++path;
|
|
||||||
}
|
|
||||||
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
XMLNode* XMLNode::get_child_relative(const char*& path, bool create)
|
|
||||||
{
|
{
|
||||||
const char* slash = strchr(path, '/');
|
const char* slash = strchr(path, '/');
|
||||||
if (slash == path)
|
if (slash == path)
|
||||||
|
@ -192,8 +151,7 @@ XMLNode* XMLNode::get_child_relative(const char*& path, bool create)
|
||||||
// look for [n] and [@attr_name="attr_value"] expressions in path components
|
// look for [n] and [@attr_name="attr_value"] expressions in path components
|
||||||
const char* bracket = strchr(comp.c_str(), '[');
|
const char* bracket = strchr(comp.c_str(), '[');
|
||||||
l = bracket? bracket-comp.c_str(): comp.length();
|
l = bracket? bracket-comp.c_str(): comp.length();
|
||||||
std::string child_name(comp.c_str(), l);
|
_child_name.assign(comp.c_str(), l);
|
||||||
std::string attr_name, attr_value;
|
|
||||||
|
|
||||||
int n = 0;
|
int n = 0;
|
||||||
if (bracket) {
|
if (bracket) {
|
||||||
|
@ -203,7 +161,7 @@ XMLNode* XMLNode::get_child_relative(const char*& path, bool create)
|
||||||
n = atoi(p); // read index number
|
n = atoi(p); // read index number
|
||||||
|
|
||||||
if (n)
|
if (n)
|
||||||
n = n - 1; // convert into zero based index
|
_child_idx = n - 1; // convert into zero based index
|
||||||
|
|
||||||
const char* at = strchr(p, '@');
|
const char* at = strchr(p, '@');
|
||||||
|
|
||||||
|
@ -213,30 +171,198 @@ XMLNode* XMLNode::get_child_relative(const char*& path, bool create)
|
||||||
|
|
||||||
// read attribute name and value
|
// read attribute name and value
|
||||||
if (equal) {
|
if (equal) {
|
||||||
attr_name = unescape(p, equal-p);
|
_attr_name = unescape(p, equal-p);
|
||||||
attr_value = unescape(equal+1);
|
_attr_value = unescape(equal+1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
XMLNode* child;
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
if (attr_name.empty())
|
XMLNode* XPathElement::find(XMLNode* node) const
|
||||||
// search n.th child node with specified name
|
{
|
||||||
child = find(child_name, n);
|
int n = 0;
|
||||||
|
|
||||||
|
for(XMLNode::Children::const_iterator it=node->_children.begin(); it!=node->_children.end(); ++it)
|
||||||
|
if (matches(**it, n))
|
||||||
|
return *it;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const XMLNode* XPathElement::const_find(const XMLNode* node) const
|
||||||
|
{
|
||||||
|
int n = 0;
|
||||||
|
|
||||||
|
for(XMLNode::Children::const_iterator it=node->_children.begin(); it!=node->_children.end(); ++it)
|
||||||
|
if (matches(**it, n))
|
||||||
|
return *it;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool XPathElement::matches(const XMLNode& node, int& n) const
|
||||||
|
{
|
||||||
|
if (node != _child_name)
|
||||||
|
if (_child_name != XS_TEXT("*")) // use asterisk as wildcard
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!_attr_name.empty())
|
||||||
|
if (node.get(_attr_name) != _attr_value)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (_child_idx == -1)
|
||||||
|
return true;
|
||||||
|
else if (n++ == _child_idx)
|
||||||
|
return true;
|
||||||
else
|
else
|
||||||
// search n.th child node with specified name and matching attribute value
|
return false;
|
||||||
child = find(child_name, attr_name, attr_value, n);
|
}
|
||||||
|
|
||||||
if (!child && create) {
|
|
||||||
child = new XMLNode(child_name);
|
|
||||||
add_child(child);
|
|
||||||
|
|
||||||
if (!attr_name.empty())
|
void XPath::init(const char* path)
|
||||||
(*this)[attr_name] = attr_value;
|
{
|
||||||
|
// Is this an absolute path?
|
||||||
|
if (*path == '/') {
|
||||||
|
_absolute = true;
|
||||||
|
++path;
|
||||||
|
} else
|
||||||
|
_absolute = false;
|
||||||
|
|
||||||
|
// parse path
|
||||||
|
while(*path) {
|
||||||
|
XPathElement elem;
|
||||||
|
|
||||||
|
path = elem.parse(path);
|
||||||
|
|
||||||
|
if (!path)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (*path == '/')
|
||||||
|
++path;
|
||||||
|
|
||||||
|
push_back(elem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const XMLNode* XMLNode::find_relative(const XPath& xpath) const
|
||||||
|
{
|
||||||
|
const XMLNode* node = this;
|
||||||
|
|
||||||
|
for(XPath::const_iterator it=xpath.begin(); it!=xpath.end(); ++it) {
|
||||||
|
node = it->const_find(node);
|
||||||
|
|
||||||
|
if (!node)
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return child;
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
XMLNode* XMLNode::find_relative(const XPath& xpath)
|
||||||
|
{
|
||||||
|
XMLNode* node = this;
|
||||||
|
|
||||||
|
for(XPath::const_iterator it=xpath.begin(); it!=xpath.end(); ++it) {
|
||||||
|
node = it->find(node);
|
||||||
|
|
||||||
|
if (!node)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
XMLNode* XMLNode::create_relative(const XPath& xpath)
|
||||||
|
{
|
||||||
|
XMLNode* node = this;
|
||||||
|
|
||||||
|
for(XPath::const_iterator it=xpath.begin(); it!=xpath.end(); ++it) {
|
||||||
|
XMLNode* child = it->find(this);
|
||||||
|
|
||||||
|
if (!child) {
|
||||||
|
child = new XMLNode(it->_child_name);
|
||||||
|
add_child(child);
|
||||||
|
|
||||||
|
if (!it->_attr_name.empty())
|
||||||
|
(*this)[it->_attr_name] = it->_attr_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// count the nodes matching the given relative XPath expression
|
||||||
|
int XMLNode::count(XPath::const_iterator from, const XPath::const_iterator& to) const
|
||||||
|
{
|
||||||
|
const XPathElement& elem = *from++;
|
||||||
|
int cnt = 0;
|
||||||
|
int n = 0;
|
||||||
|
|
||||||
|
for(XMLNode::Children::const_iterator it=_children.begin(); it!=_children.end(); ++it)
|
||||||
|
if (elem.matches(**it, n))
|
||||||
|
if (from != to)
|
||||||
|
// iterate deeper
|
||||||
|
cnt += (*it)->count(from, to);
|
||||||
|
else
|
||||||
|
// increment match counter
|
||||||
|
++cnt;
|
||||||
|
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// copy matching tree nodes using the given XPath filter expression
|
||||||
|
bool XMLNode::filter(const XPath& xpath, XMLNode& target) const
|
||||||
|
{
|
||||||
|
XMLNode* ret = filter(xpath.begin(), xpath.end());
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
// move returned nodes to target node
|
||||||
|
target._children.move(ret->_children);
|
||||||
|
target._attributes = ret->_attributes;
|
||||||
|
|
||||||
|
delete ret;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// create a new node tree using the given XPath filter expression
|
||||||
|
XMLNode* XMLNode::filter(XPath::const_iterator from, const XPath::const_iterator& to) const
|
||||||
|
{
|
||||||
|
XMLNode* copy = NULL;
|
||||||
|
|
||||||
|
const XPathElement& elem = *from++;
|
||||||
|
int cnt = 0;
|
||||||
|
int n = 0;
|
||||||
|
|
||||||
|
for(XMLNode::Children::const_iterator it=_children.begin(); it!=_children.end(); ++it)
|
||||||
|
if (elem.matches(**it, n)) {
|
||||||
|
if (!copy)
|
||||||
|
copy = new XMLNode(*this, XMLNode::COPY_NOCHILDREN);
|
||||||
|
|
||||||
|
if (from != to) {
|
||||||
|
XMLNode* ret = (*it)->filter(from, to);
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
copy->add_child(ret);
|
||||||
|
++cnt;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
copy->add_child(new XMLNode(**it, XMLNode::COPY_NOCHILDREN));
|
||||||
|
++cnt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cnt > 0) {
|
||||||
|
return copy;
|
||||||
|
} else {
|
||||||
|
delete copy;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -286,9 +412,9 @@ std::string EncodeXMLString(const XS_String& str, bool cdata)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if ((unsigned)*p<20 && *p!='\t' && *p!='\r' && *p!='\n') {
|
if ((unsigned)*p<0x20 && *p!='\t' && *p!='\r' && *p!='\n') {
|
||||||
char b[16];
|
char b[16];
|
||||||
sprintf(b, "&%d;", (unsigned)*p);
|
sprintf(b, "&#%d;", (unsigned)*p);
|
||||||
for(const char*q=b; *q; )
|
for(const char*q=b; *q; )
|
||||||
*o++ = *q++;
|
*o++ = *q++;
|
||||||
} else
|
} else
|
||||||
|
@ -330,8 +456,8 @@ std::string EncodeXMLString(const XS_String& str, bool cdata)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if ((unsigned)*p<20 && *p!='\t' && *p!='\r' && *p!='\n')
|
if ((unsigned)*p<0x20 && *p!='\t' && *p!='\r' && *p!='\n')
|
||||||
out << "&" << (unsigned)*p << ";";
|
out << "&#" << (unsigned)*p << ";";
|
||||||
else
|
else
|
||||||
out << *p;
|
out << *p;
|
||||||
}
|
}
|
||||||
|
@ -368,7 +494,7 @@ XS_String DecodeXMLString(const XS_String& str)
|
||||||
} else if (!XS_nicmp(p+1, XS_TEXT("apos;"), 5)) {
|
} else if (!XS_nicmp(p+1, XS_TEXT("apos;"), 5)) {
|
||||||
*o++ = '\'';
|
*o++ = '\'';
|
||||||
p += 5;
|
p += 5;
|
||||||
} else
|
} else //@@ maybe decode "&#xx;" special characters
|
||||||
*o++ = *p;
|
*o++ = *p;
|
||||||
} else if (*p=='<' && !XS_nicmp(p+1,XS_TEXT("![CDATA["),8)) {
|
} else if (*p=='<' && !XS_nicmp(p+1,XS_TEXT("![CDATA["),8)) {
|
||||||
LPCXSSTR e = XS_strstr(p+9, XS_TEXT("]]>"));
|
LPCXSSTR e = XS_strstr(p+9, XS_TEXT("]]>"));
|
||||||
|
@ -535,18 +661,33 @@ std::ostream& operator<<(std::ostream& out, const XMLError& err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char* get_xmlsym_end_utf8(const char* p)
|
||||||
|
{
|
||||||
|
for(; *p; ++p) {
|
||||||
|
char c = *p;
|
||||||
|
|
||||||
|
if (c == '\xC3') // UTF-8 escape character
|
||||||
|
++p; //TODO only continue on umlaut characters
|
||||||
|
else if (!isalnum(c) && c!='_' && c!='-')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DocType::parse(const char* p)
|
void DocType::parse(const char* p)
|
||||||
{
|
{
|
||||||
while(isspace((unsigned char)*p)) ++p;
|
while(isspace((unsigned char)*p)) ++p;
|
||||||
|
|
||||||
const char* start = p;
|
const char* start = p;
|
||||||
while(isxmlsym(*p)) ++p;
|
p = get_xmlsym_end_utf8(p);
|
||||||
_name.assign(start, p-start);
|
_name.assign(start, p-start);
|
||||||
|
|
||||||
while(isspace((unsigned char)*p)) ++p;
|
while(isspace((unsigned char)*p)) ++p;
|
||||||
|
|
||||||
start = p;
|
start = p;
|
||||||
while(isxmlsym(*p)) ++p;
|
p = get_xmlsym_end_utf8(p);
|
||||||
std::string keyword(p, p-start); // "PUBLIC" or "SYSTEM"
|
std::string keyword(p, p-start); // "PUBLIC" or "SYSTEM"
|
||||||
|
|
||||||
while(isspace((unsigned char)*p)) ++p;
|
while(isspace((unsigned char)*p)) ++p;
|
||||||
|
@ -705,7 +846,6 @@ void XMLReaderBase::StartElementHandler(const XS_String& name, const XMLNode::At
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (p != s)
|
if (p != s)
|
||||||
{
|
|
||||||
if (_pos->_children.empty()) { // no children in last node?
|
if (_pos->_children.empty()) { // no children in last node?
|
||||||
if (_last_tag == TAG_START)
|
if (_last_tag == TAG_START)
|
||||||
_pos->_content.append(s, p-s);
|
_pos->_content.append(s, p-s);
|
||||||
|
@ -715,7 +855,7 @@ void XMLReaderBase::StartElementHandler(const XS_String& name, const XMLNode::At
|
||||||
p = s;
|
p = s;
|
||||||
} else
|
} else
|
||||||
_pos->_children.back()->_trailing.append(s, p-s);
|
_pos->_children.back()->_trailing.append(s, p-s);
|
||||||
}
|
|
||||||
std::string leading;
|
std::string leading;
|
||||||
|
|
||||||
if (p != e)
|
if (p != e)
|
||||||
|
@ -753,14 +893,12 @@ void XMLReaderBase::EndElementHandler()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p != s)
|
if (p != s)
|
||||||
{
|
|
||||||
if (_pos->_children.empty()) // no children in current node?
|
if (_pos->_children.empty()) // no children in current node?
|
||||||
_pos->_content.append(s, p-s);
|
_pos->_content.append(s, p-s);
|
||||||
else if (_last_tag == TAG_START)
|
else if (_last_tag == TAG_START)
|
||||||
_pos->_content.append(s, p-s);
|
_pos->_content.append(s, p-s);
|
||||||
else
|
else
|
||||||
_pos->_children.back()->_trailing.append(s, p-s);
|
_pos->_children.back()->_trailing.append(s, p-s);
|
||||||
}
|
|
||||||
|
|
||||||
if (p != e)
|
if (p != e)
|
||||||
_pos->_end_leading.assign(p, e-p);
|
_pos->_end_leading.assign(p, e-p);
|
||||||
|
@ -786,5 +924,91 @@ void XMLReaderBase::DefaultHandler(const XML_Char* s, int len)
|
||||||
|
|
||||||
XS_String XMLWriter::s_empty_attr;
|
XS_String XMLWriter::s_empty_attr;
|
||||||
|
|
||||||
|
void XMLWriter::create(const XS_String& name)
|
||||||
|
{
|
||||||
|
if (!_stack.empty()) {
|
||||||
|
StackEntry& last = _stack.top();
|
||||||
|
|
||||||
|
if (last._state < PRE_CLOSED) {
|
||||||
|
write_attributes(last);
|
||||||
|
close_pre(last);
|
||||||
|
}
|
||||||
|
|
||||||
|
++last._children;
|
||||||
|
}
|
||||||
|
|
||||||
|
StackEntry entry;
|
||||||
|
entry._node_name = name;
|
||||||
|
_stack.push(entry);
|
||||||
|
|
||||||
|
write_pre(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool XMLWriter::back()
|
||||||
|
{
|
||||||
|
if (!_stack.empty()) {
|
||||||
|
write_post(_stack.top());
|
||||||
|
|
||||||
|
_stack.pop();
|
||||||
|
return true;
|
||||||
|
} else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void XMLWriter::close_pre(StackEntry& entry)
|
||||||
|
{
|
||||||
|
_out << '>';
|
||||||
|
|
||||||
|
entry._state = PRE_CLOSED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void XMLWriter::write_pre(StackEntry& entry)
|
||||||
|
{
|
||||||
|
if (_format._pretty >= PRETTY_LINEFEED)
|
||||||
|
_out << _format._endl;
|
||||||
|
|
||||||
|
if (_format._pretty == PRETTY_INDENT)
|
||||||
|
for(size_t i=_stack.size(); --i>0; )
|
||||||
|
_out << XML_INDENT_SPACE;
|
||||||
|
|
||||||
|
_out << '<' << EncodeXMLString(entry._node_name);
|
||||||
|
//entry._state = PRE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void XMLWriter::write_attributes(StackEntry& entry)
|
||||||
|
{
|
||||||
|
for(AttrMap::const_iterator it=entry._attributes.begin(); it!=entry._attributes.end(); ++it)
|
||||||
|
_out << ' ' << EncodeXMLString(it->first) << "=\"" << EncodeXMLString(it->second) << "\"";
|
||||||
|
|
||||||
|
entry._state = ATTRIBUTES;
|
||||||
|
}
|
||||||
|
|
||||||
|
void XMLWriter::write_post(StackEntry& entry)
|
||||||
|
{
|
||||||
|
if (entry._state < ATTRIBUTES)
|
||||||
|
write_attributes(entry);
|
||||||
|
|
||||||
|
if (entry._children || !entry._content.empty()) {
|
||||||
|
if (entry._state < PRE_CLOSED)
|
||||||
|
close_pre(entry);
|
||||||
|
|
||||||
|
_out << entry._content;
|
||||||
|
//entry._state = CONTENT;
|
||||||
|
|
||||||
|
if (_format._pretty>=PRETTY_LINEFEED && entry._content.empty())
|
||||||
|
_out << _format._endl;
|
||||||
|
|
||||||
|
if (_format._pretty==PRETTY_INDENT && entry._content.empty())
|
||||||
|
for(size_t i=_stack.size(); --i>0; )
|
||||||
|
_out << XML_INDENT_SPACE;
|
||||||
|
|
||||||
|
_out << "</" << EncodeXMLString(entry._node_name) << ">";
|
||||||
|
} else {
|
||||||
|
_out << "/>";
|
||||||
|
}
|
||||||
|
|
||||||
|
entry._state = POST;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace XMLStorage
|
} // namespace XMLStorage
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,8 +1,8 @@
|
||||||
|
|
||||||
//
|
//
|
||||||
// XML storage C++ classes version 1.2
|
// XML storage C++ classes version 1.3
|
||||||
//
|
//
|
||||||
// Copyright (c) 2006, 2007 Martin Fuchs <martin-fuchs@gmx.net>
|
// Copyright (c) 2006, 2007, 2008 Martin Fuchs <martin-fuchs@gmx.net>
|
||||||
//
|
//
|
||||||
|
|
||||||
/// \file xs-native.cpp
|
/// \file xs-native.cpp
|
||||||
|
@ -94,7 +94,7 @@ struct Buffer
|
||||||
_buffer_str.erase();
|
_buffer_str.erase();
|
||||||
}
|
}
|
||||||
|
|
||||||
void append(char c)
|
void append(int c)
|
||||||
{
|
{
|
||||||
size_t wpos = _wptr-_buffer;
|
size_t wpos = _wptr-_buffer;
|
||||||
|
|
||||||
|
@ -104,7 +104,7 @@ struct Buffer
|
||||||
_wptr = _buffer + wpos;
|
_wptr = _buffer + wpos;
|
||||||
}
|
}
|
||||||
|
|
||||||
*_wptr++ = c;
|
*_wptr++ = static_cast<char>(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& str(bool utf8) // returns UTF-8 encoded buffer content
|
const std::string& str(bool utf8) // returns UTF-8 encoded buffer content
|
||||||
|
@ -149,8 +149,7 @@ struct Buffer
|
||||||
if (*q == '?')
|
if (*q == '?')
|
||||||
++q;
|
++q;
|
||||||
|
|
||||||
while(isxmlsym(*q))
|
q = get_xmlsym_end_utf8(q);
|
||||||
++q;
|
|
||||||
|
|
||||||
#ifdef XS_STRING_UTF8
|
#ifdef XS_STRING_UTF8
|
||||||
return XS_String(p, q-p);
|
return XS_String(p, q-p);
|
||||||
|
@ -175,8 +174,7 @@ struct Buffer
|
||||||
else if (*p == '?')
|
else if (*p == '?')
|
||||||
++p;
|
++p;
|
||||||
|
|
||||||
while(isxmlsym(*p))
|
p = get_xmlsym_end_utf8(p);
|
||||||
++p;
|
|
||||||
|
|
||||||
// read attributes from buffer
|
// read attributes from buffer
|
||||||
while(*p && *p!='>' && *p!='/') {
|
while(*p && *p!='>' && *p!='/') {
|
||||||
|
@ -185,8 +183,7 @@ struct Buffer
|
||||||
|
|
||||||
const char* attr_name = p;
|
const char* attr_name = p;
|
||||||
|
|
||||||
while(isxmlsym(*p))
|
p = get_xmlsym_end_utf8(p);
|
||||||
++p;
|
|
||||||
|
|
||||||
if (*p != '=')
|
if (*p != '=')
|
||||||
break; //@TODO error handling
|
break; //@TODO error handling
|
||||||
|
@ -360,8 +357,7 @@ bool XMLReaderBase::parse()
|
||||||
// read white space
|
// read white space
|
||||||
for(;;) {
|
for(;;) {
|
||||||
// check for the encoding of the first line end
|
// check for the encoding of the first line end
|
||||||
if (!_endl_defined)
|
if (!_endl_defined) {
|
||||||
{
|
|
||||||
if (c == '\n') {
|
if (c == '\n') {
|
||||||
_format._endl = "\n";
|
_format._endl = "\n";
|
||||||
_endl_defined = true;
|
_endl_defined = true;
|
||||||
|
@ -370,6 +366,7 @@ bool XMLReaderBase::parse()
|
||||||
_endl_defined = true;
|
_endl_defined = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c = get();
|
c = get();
|
||||||
|
|
||||||
if (c == EOF)
|
if (c == EOF)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue