xmlstorage.h
字号:
}
void set_content(const XS_String& s)
{
_content.assign(EncodeXMLString(s.c_str()));
}
#ifdef XMLNODE_LOCATION
const XMLLocation& get_location() const {return _location;}
#endif
enum WRITE_MODE {
FORMAT_SMART = 0, /// preserve original white space and comments if present; pretty print otherwise
FORMAT_ORIGINAL = 1, /// write XML stream preserving original white space and comments
FORMAT_PRETTY = 2 /// pretty print node to stream without preserving original white space
};
/// write node with children tree to output stream
std::ostream& write(std::ostream& out, WRITE_MODE mode=FORMAT_SMART, int indent=0) const
{
switch(mode) {
case FORMAT_PRETTY:
pretty_write_worker(out, indent);
break;
case FORMAT_ORIGINAL:
write_worker(out, indent);
break;
default: // FORMAT_SMART
smart_write_worker(out, indent);
}
return out;
}
protected:
Children _children;
AttributeMap _attributes;
std::string _leading;
std::string _content;
std::string _end_leading;
std::string _trailing;
#ifdef XMLNODE_LOCATION
XMLLocation _location;
#endif
XMLNode* get_first_child() const
{
if (!_children.empty())
return _children.front();
else
return NULL;
}
XMLNode* find(const XS_String& name, int n=0) const
{
for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it)
if (**it == name)
if (!n--)
return *it;
return NULL;
}
XMLNode* find(const XS_String& name, const XS_String& attr_name, const XS_String& attr_value, int n=0) const
{
for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it) {
const XMLNode& node = **it;
if (node==name && node.get(attr_name)==attr_value)
if (!n--)
return *it;
}
return NULL;
}
#if defined(UNICODE) && !defined(XS_STRING_UTF8)
XMLNode* find(const char* name, int n=0) const
{
for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it)
if (**it == name)
if (!n--)
return *it;
return NULL;
}
template<typename T, typename U>
XMLNode* find(const char* name, const T& attr_name, const U& attr_value, int n=0) const
{
for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it) {
const XMLNode& node = **it;
if (node==name && node.get(attr_name)==attr_value)
if (!n--)
return *it;
}
return NULL;
}
#endif
/// XPath find function (const)
const XMLNode* find_relative(const char* path) const;
/// XPath find function
XMLNode* find_relative(const char* path)
{return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->find_relative(path));}
/// relative XPath create function
XMLNode* create_relative(const char* path);
void write_worker(std::ostream& out, int indent) const;
void pretty_write_worker(std::ostream& out, int indent) const;
void smart_write_worker(std::ostream& out, int indent) const;
};
/// iterator access to children nodes with name filtering
struct XMLChildrenFilter
{
XMLChildrenFilter(XMLNode::Children& children, const XS_String& name)
: _begin(children.begin(), children.end(), name),
_end(children.end(), children.end(), name)
{
}
XMLChildrenFilter(XMLNode* node, const XS_String& name)
: _begin(node->get_children().begin(), node->get_children().end(), name),
_end(node->get_children().end(), node->get_children().end(), name)
{
}
/// internal iterator class
struct iterator
{
typedef XMLNode::Children::iterator BaseIterator;
iterator(BaseIterator begin, BaseIterator end, const XS_String& filter_name)
: _cur(begin),
_end(end),
_filter_name(filter_name)
{
search_next();
}
operator BaseIterator()
{
return _cur;
}
const XMLNode* operator*() const
{
return *_cur;
}
XMLNode* operator*()
{
return *_cur;
}
iterator& operator++()
{
++_cur;
search_next();
return *this;
}
iterator operator++(int)
{
iterator ret = *this;
++_cur;
search_next();
return ret;
}
bool operator==(const BaseIterator& other) const
{
return _cur == other;
}
bool operator!=(const BaseIterator& other) const
{
return _cur != other;
}
protected:
BaseIterator _cur;
BaseIterator _end;
XS_String _filter_name;
void search_next()
{
while(_cur!=_end && **_cur!=_filter_name)
++_cur;
}
};
iterator begin()
{
return _begin;
}
iterator end()
{
return _end;
}
protected:
iterator _begin;
iterator _end;
};
/// read only iterator access to children nodes with name filtering
struct const_XMLChildrenFilter
{
const_XMLChildrenFilter(const XMLNode::Children& children, const XS_String& name)
: _begin(children.begin(), children.end(), name),
_end(children.end(), children.end(), name)
{
}
const_XMLChildrenFilter(const XMLNode* node, const XS_String& name)
: _begin(node->get_children().begin(), node->get_children().end(), name),
_end(node->get_children().end(), node->get_children().end(), name)
{
}
/// internal iterator class
struct const_iterator
{
typedef XMLNode::Children::const_iterator BaseIterator;
const_iterator(BaseIterator begin, BaseIterator end, const XS_String& filter_name)
: _cur(begin),
_end(end),
_filter_name(filter_name)
{
search_next();
}
operator BaseIterator()
{
return _cur;
}
const XMLNode* operator*() const
{
return *_cur;
}
const_iterator& operator++()
{
++_cur;
search_next();
return *this;
}
const_iterator operator++(int)
{
const_iterator ret = *this;
++_cur;
search_next();
return ret;
}
bool operator==(const BaseIterator& other) const
{
return _cur == other;
}
bool operator!=(const BaseIterator& other) const
{
return _cur != other;
}
protected:
BaseIterator _cur;
BaseIterator _end;
XS_String _filter_name;
void search_next()
{
while(_cur!=_end && **_cur!=_filter_name)
++_cur;
}
};
const_iterator begin()
{
return _begin;
}
const_iterator end()
{
return _end;
}
protected:
const_iterator _begin;
const_iterator _end;
};
/// iterator for XML trees
struct XMLPos
{
XMLPos(XMLNode* root)
: _root(root),
_cur(root)
{
}
XMLPos(const XMLPos& other)
: _root(other._root),
_cur(other._cur)
{ // don't copy _stack
}
XMLPos(XMLNode* node, const XS_String& name)
: _root(node),
_cur(node)
{
smart_create(name);
}
XMLPos(XMLNode* node, const XS_String& name, const XS_String& attr_name, const XS_String& attr_value)
: _root(node),
_cur(node)
{
smart_create(name, attr_name, attr_value);
}
XMLPos(const XMLPos& other, const XS_String& name)
: _root(other._root),
_cur(other._cur)
{
smart_create(name);
}
XMLPos(const XMLPos& other, const XS_String& name, const XS_String& attr_name, const XS_String& attr_value)
: _root(other._root),
_cur(other._cur)
{
smart_create(name, attr_name, attr_value);
}
/// access to current node
XMLNode& cur()
{
return *_cur;
}
const XMLNode& cur() const
{
return *_cur;
}
/// C++ access to current node
operator const XMLNode*() const {return _cur;}
operator XMLNode*() {return _cur;}
const XMLNode* operator->() const {return _cur;}
XMLNode* operator->() {return _cur;}
const XMLNode& operator*() const {return *_cur;}
XMLNode& operator*() {return *_cur;}
/// attribute access
XS_String get(const XS_String& attr_name) const
{
return _cur->get(attr_name);
}
/// attribute setting
void put(const XS_String& attr_name, const XS_String& value)
{
_cur->put(attr_name, value);
}
/// C++ attribute access
template<typename T> XS_String get(const T& attr_name) const {return (*_cur)[attr_name];}
XS_String& operator[](const XS_String& attr_name) {return (*_cur)[attr_name];}
/// insert children when building tree
void add_down(XMLNode* child)
{
_cur->add_child(child);
go_to(child);
}
/// go back to previous position
bool back()
{
if (!_stack.empty()) {
_cur = _stack.top();
_stack.pop();
return true;
} else
return false;
}
/// go down to first child
bool go_down()
{
XMLNode* node = _cur->get_first_child();
if (node) {
go_to(node);
return true;
} else
return false;
}
/// search for child and go down
bool go_down(const XS_String& name, int n=0)
{
XMLNode* node = _cur->find(name, n);
if (node) {
go_to(node);
return true;
} else
return false;
}
/// move XPath like to position in XML tree
bool go(const char* path);
/// create child nodes using XPath notation and move to the deepest child
bool create_relative(const char* path)
{
XMLNode* node = _cur->create_relative(path);
if (!node)
return false; // invalid path specified
go_to(node);
return true;
}
/// create node and move to it
void create(const XS_String& name)
{
add_down(new XMLNode(name));
}
/// create node if not already existing and move to it
void smart_create(const XS_String& name)
{
XMLNode* node = _cur->find(name);
if (node)
go_to(node);
else
add_down(new XMLNode(name));
}
/// search matching child node identified by key name and an attribute value
void smart_create(const XS_String& name, const XS_String& attr_name, const XS_String& attr_value)
{
XMLNode* node = _cur->find(name, attr_name, attr_value);
if (node)
go_to(node);
else {
node = new XMLNode(name);
add_down(node);
(*node)[attr_name] = attr_value;
}
}
#if defined(UNICODE) && !defined(XS_STRING_UTF8)
/// search for child and go down
bool go_down(const char* name, int n=0)
{
XMLNode* node = _cur->find(name, n);
if (node) {
go_to(node);
return true;
} else
return false;
}
/// create node and move to it
void create(const char* name)
{
add_down(new XMLNode(name));
}
/// create node if not already existing and move to it
void smart_create(const char* name)
{
XMLNode* node = _cur->find(name);
if (node)
go_to(node);
else
add_down(new XMLNode(name));
}
/// search matching child node identified by key name and an attribute value
template<typename T, typename U>
void smart_create(const char* name, const T& attr_name, const U& attr_value)
{
XMLNode* node = _cur->find(name, attr_name, attr_value);
if (node)
go_to(node);
else {
XMLNode* node = new XMLNode(name);
add_down(node);
(*node)[attr_name] = attr_value;
}
}
#endif
XS_String& str() {return *_cur;}
const XS_String& str() const {return *_cur;}
protected:
XMLNode* _root;
XMLNode* _cur;
std::stack<XMLNode*> _stack;
/// go to specified node
void go_to(XMLNode* child)
{
_stack.push(_cur);
_cur = child;
}
};
/// iterator for XML trees
struct const_XMLPos
{
const_XMLPos(const XMLNode* root)
: _root(root),
_cur(root)
{
}
const_XMLPos(const const_XMLPos& other)
: _root(other._root),
_cur(other._cur)
{ // don't copy _stack
}
/// access to current node
const XMLNode& cur() const
{
return *_cur;
}
/// C++ access to current node
operator const XMLNode*() const {return _cur;}
const XMLNode* operator->() const {return _cur;}
const XMLNode& operator*() const {return *_cur;}
/// attribute access
XS_String get(const XS_String& attr_name) const
{
return _cur->get(attr_name);
}
/// C++ attribute access
template<typename T> XS_String get(const T& attr_name) const {return _cur->get(attr_name);}
/// go back to previous position
bool back()
{
if (!_stack.empty()) {
_cur = _stack.top();
_stack.pop();
return true;
} else
return false;
}
/// go down to first child
bool go_down()
{
const XMLNode* node = _cur->get_first_child();
if (node) {
go_to(node);
return true;
} else
return false;
}
/// search for child and go down
bool go_down(const XS_String& name, int n=0)
{
XMLNode* node = _cur->find(name, n);
if (node) {
go_to(node);
return true;
} else
return false;
}
/// move XPath like to position in XML tree
bool go(const char* path);
#if defined(UNICODE) && !defined(XS_STRING_UTF8)
/// search for child and go down
bool go_down(const char* name, int n=0)
{
XMLNode* node = _cur->find(name, n);
if (node) {
go_to(node);
return true;
} else
return false;
}
#endif
const XS_String& str() const {return *_cur;}
protected:
const XMLNode* _root;
const XMLNode* _cur;
std::stack<const XMLNode*> _stack;
/// go to specified node
void go_to(const XMLNode* child)
{
_stack.push(_cur);
_cur = child;
}
};
#define XS_TRUE_STR XS_TEXT("true")
#define XS_FALSE_STR XS_TEXT("false")
#define XS_INTFMT_STR XS_TEXT("%d")
#define XS_FLOATFMT_STR XS_TEXT("%f")
// work around GCC's wide string constant bug
#ifdef __GNUC__
extern const LPCXSSTR XS_TRUE;
extern const LPCXSSTR XS_FALSE;
extern const LPCXSSTR XS_INTFMT;
extern const LPCXSSTR XS_FLOATFMT;
#else
#define XS_TRUE XS_TRUE_STR
#define XS_FALSE XS_FALSE_STR
#define XS_INTFMT XS_INTFMT_STR
#define XS_FLOATFMT XS_FLOATFMT_STR
#endif
/// type converter for boolean data
struct XMLBool
{
XMLBool(bool value=false)
: _value(value)
{
}
XMLBool(LPCXSSTR value, bool def=false)
{
if (value && *value)
_value = !XS_icmp(value, XS_TRUE);
else
_value = def;
}
XMLBool(const XMLNode* node, const XS_String& attr_name, bool def=false)
{
const XS_String& value = node->get(attr_name);
if (!value.empty())
_value = !XS_icmp(value.c_str(), XS_TRUE);
else
_value = def;
}
operator bool() const
{
return _value;
}
bool operator!() const
{
return !_value;
}
operator LPCXSSTR() const
{
return _value? XS_TRUE: XS_FALSE;
}
protected:
bool _value;
private:
void operator=(const XMLBool&); // disallow assignment operations
};
/// type converter for boolean data with write access
struct XMLBoolRef
{
XMLBoolRef(XMLNode* node, const XS_String& attr_name, bool def=false)
: _ref((*node)[attr_name])
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -