📄 xmlstorage.h
字号:
std::string _href; // CDATA #REQUIRED
std::string _type; // CDATA #REQUIRED
std::string _title; // CDATA #IMPLIED
std::string _media; // CDATA #IMPLIED
std::string _charset; // CDATA #IMPLIED
bool _alternate; // (yes|no) "no"
StyleSheet() : _alternate(false) {}
StyleSheet(const std::string& href, const std::string& type="text/xsl", bool alternate=false)
: _href(href),
_type(type),
_alternate(alternate)
{
}
bool empty() const {return _href.empty();}
void print(std::ostream& out) const;
};
/// list of StyleSheet entries
struct StyleSheetList : public std::list<StyleSheet>
{
void set(const StyleSheet& stylesheet)
{
clear();
push_back(stylesheet);
}
};
/// XML document type description
struct DocType
{
std::string _name;
// External Document Types are noted, but not parsed.
std::string _public;
std::string _system;
// Internal DTDs are not supported.
void parse(const char* str);
bool empty() const {return _name.empty();}
};
/// Management of XML file headers and formating
struct XMLFormat
{
XMLFormat(PRETTY_FLAGS pretty=PRETTY_INDENT, const std::string& xml_version="1.0", const std::string& encoding="utf-8", const DocType& doctype=DocType())
: _pretty(pretty),
_endl("\n"),
_version(xml_version),
_encoding(encoding),
_doctype(doctype),
_standalone(-1)
{
}
void print_header(std::ostream& out, bool lf=true) const;
PRETTY_FLAGS _pretty;
const char* _endl; // line ending string: "\n" or "\r\n"
std::string _version;
std::string _encoding;
DocType _doctype;
StyleSheetList _stylesheets;
// std::string _additional;
int _standalone;
};
enum WRITE_MODE {
FORMAT_PLAIN, /// write XML without any white space
FORMAT_SMART, /// preserve original white space and comments if present; pretty print otherwise
FORMAT_ORIGINAL, /// write XML stream preserving original white space and comments
FORMAT_PRETTY /// pretty print node to stream without preserving original white space
};
/// in memory representation of an XML node
struct XMLNode : public XS_String
{
#if defined(UNICODE) && !defined(XS_STRING_UTF8)
/// map of XML node attributes
// optimized read access without temporary A/U conversion when using ASCII attribute names
struct AttributeMap : public std::map<XS_String, XS_String>
{
typedef std::map<XS_String, XS_String> super;
const_iterator find(const char* x) const
{
for(const_iterator it=begin(); it!=end(); ++it)
if (it->first == x)
return it;
return end();
}
const_iterator find(const key_type& x) const
{
return super::find(x);
}
iterator find(const key_type& x)
{
return super::find(x);
}
XS_String get(const char* x, LPCXSSTR def=XS_EMPTY_STR) const
{
const_iterator found = find(x);
if (found != end())
return found->second;
else
return def;
}
};
#else
/// map of XML node attributes
struct AttributeMap : public std::map<XS_String, XS_String>
{
XS_String get(const char* x, LPCXSSTR def=XS_EMPTY_STR) const
{
const_iterator found = find(x);
if (found != end())
return found->second;
else
return def;
}
};
#endif
/// internal children node list
struct Children : public std::list<XMLNode*>
{
void assign(const Children& other)
{
clear();
for(Children::const_iterator it=other.begin(); it!=other.end(); ++it)
push_back(new XMLNode(**it));
}
void clear()
{
while(!empty()) {
XMLNode* node = back();
pop_back();
node->clear();
delete node;
}
}
};
// access to protected class members for XMLPos and XMLReader
friend struct XMLPos;
friend struct const_XMLPos;
friend struct XMLReaderBase;
XMLNode(const XS_String& name)
: XS_String(name)
{
}
XMLNode(const XS_String& name, const std::string& leading)
: XS_String(name),
_leading(leading)
{
}
XMLNode(const XMLNode& other)
: XS_String(other),
_attributes(other._attributes),
_leading(other._leading),
_content(other._content),
_end_leading(other._end_leading),
_trailing(other._trailing)
#ifdef XMLNODE_LOCATION
, _location(other._location)
#endif
{
for(Children::const_iterator it=other._children.begin(); it!=other._children.end(); ++it)
_children.push_back(new XMLNode(**it));
}
virtual ~XMLNode()
{
while(!_children.empty()) {
delete _children.back();
_children.pop_back();
}
}
void clear()
{
_leading.erase();
_content.erase();
_end_leading.erase();
_trailing.erase();
_attributes.clear();
_children.clear();
XS_String::erase();
}
XMLNode& operator=(const XMLNode& other)
{
_children.assign(other._children);
_attributes = other._attributes;
_leading = other._leading;
_content = other._content;
_end_leading = other._end_leading;
_trailing = other._trailing;
return *this;
}
/// add a new child node
void add_child(XMLNode* child)
{
_children.push_back(child);
}
/// write access to an attribute
void put(const XS_String& attr_name, const XS_String& value)
{
_attributes[attr_name] = value;
}
/// C++ write access to an attribute
XS_String& operator[](const XS_String& attr_name)
{
return _attributes[attr_name];
}
/// read only access to an attribute
template<typename T> XS_String get(const T& attr_name, LPCXSSTR def=XS_EMPTY_STR) const
{
AttributeMap::const_iterator found = _attributes.find(attr_name);
if (found != _attributes.end())
return found->second;
else
return def;
}
/// convenient value access in children node
XS_String subvalue(const XS_String& name, const XS_String& attr_name, int n=0) const
{
const XMLNode* node = find(name, n);
if (node)
return node->get(attr_name);
else
return XS_String();
}
/// convenient storage of distinct values in children node
XS_String& subvalue(const XS_String& name, const XS_String& attr_name, int n=0)
{
XMLNode* node = find(name, n);
if (!node) {
node = new XMLNode(name);
add_child(node);
}
return (*node)[attr_name];
}
#if defined(UNICODE) && !defined(XS_STRING_UTF8)
/// convenient value access in children node
XS_String subvalue(const char* name, const char* attr_name, int n=0) const
{
const XMLNode* node = find(name, n);
if (node)
return node->get(attr_name);
else
return XS_String();
}
/// convenient storage of distinct values in children node
XS_String& subvalue(const char* name, const XS_String& attr_name, int n=0)
{
XMLNode* node = find(name, n);
if (!node) {
node = new XMLNode(name);
add_child(node);
}
return (*node)[attr_name];
}
#endif
const Children& get_children() const
{
return _children;
}
Children& get_children()
{
return _children;
}
const AttributeMap& get_attributes() const
{
return _attributes;
}
AttributeMap& get_attributes()
{
return _attributes;
}
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());
}
void set_content(const XS_String& s, bool cdata=false)
{
_content.assign(EncodeXMLString(s.c_str(), cdata));
}
#ifdef XMLNODE_LOCATION
const XMLLocation& get_location() const {return _location;}
#endif
/// write node with children tree to output stream
bool write(std::ostream& out, const XMLFormat& format, WRITE_MODE mode=FORMAT_SMART, int indent=0) const
{
switch(mode) {
case FORMAT_PLAIN:
plain_write_worker(out);
break;
case FORMAT_PRETTY:
pretty_write_worker(out, format, indent);
break;
case FORMAT_ORIGINAL:
write_worker(out, indent);
break;
default: // FORMAT_SMART
smart_write_worker(out, format, indent);
}
return out.good();
}
protected:
Children _children;
AttributeMap _attributes;
std::string _leading; // UTF-8 encoded
std::string _content; // UTF-8 and entity encoded, may contain CDATA sections; decode with DecodeXMLString()
std::string _end_leading; // UTF-8 encoded
std::string _trailing; // UTF-8 encoded
#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 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;
};
/// 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),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -