XML++ version 3: The C++11 Update of My XML Library






4.90/5 (33 votes)
The update to my beloved library. Single-header file.
- Github: https://github.com/WindowsNT/xml
Introduction
The C++11 version of my popular XML Library (http://www.codeproject.com/Articles/18732/XML-Include-a-Flexible-Parser-in-Your-C-Applicatio) with a cleaner interface, within one .h file which can be used in precompiled headers as well.
BXML
A class to represent binary data in XML. Can set/get from Base64
.
// BXML
class BXML
{
private:
vector<char> d;
public:
BXML(size_t s = 0);
bool operator ==(const BXML& b2);
void ToB(string& s);
void FromB(const char* ba);
operator const char*() const;
operator char*();
const char* p() const;
char* p();
size_t size() const;
void clear();
void reset();
void Ensure(size_t news);
void Resize(size_t news);
void AddResize(size_t More);
};
XMLContent
- Constructor can initialize from:
- Value:
XMLContent v("n");
- Another Variable:
XMLContent v2 = v;
- Value:
- Enhancements
- Set value:
v2 = "hello";
- Binary contents:
v2.SetBinaryData("\0\0\0",3);
- operator const char*():
string z = v2;
- Set value:
- Templates to set and get:
v3.SetFormattedValue<int>("%d",5);
v3.SetFormattedValue<const char*>("%s","hello");
auto j = v3.GetFormattedValue<int>("%d"); // using sscanf, j = int.
- Serialization to
string
with or without encoding.class XMLContent { protected: string v; size_t ep = 0; public: XMLContent(); XMLContent(size_t ElementPosition,const char* ht); XMLContent(size_t ElementPosition,const wchar_t* ht); size_t MemoryUsage(); // Operators bool operator==(const XMLContent& t) const; operator const string& () const; // Sets const string& SetFormattedValue(const char* fmt,...); template <typename T> const string& SetFormattedValue(const char* fmt,T ty) { unique_ptr<char> t(new char[10000]); sprintf_s(t.get(),fmt,10000,ty); SetValue(t); return v; } XMLContent& operator =(const char* s); XMLContent& operator =(const string& s); const string& SetBinaryValue(const char* data,size_t len); void SetValue(const char* VV); void SetValue(const string& VV); void Clear(); void SetEP(size_t epp); // Gets BXML GetBinaryValue() const; template <typename T> T GetFormattedValue(const char* fmt) const { T x; sscanf(v.c_str(),fmt,&x); return x; } const string& GetValue() const; size_t GetEP() const; // Serialization virtual string Serialize(bool NoEnc = false) const; };
XMLComment, XMLCData, XMLDocType and XMLVariable/XMLAttribute
All these inherit from XMLContent
. In addition, XMLVariable
includes methods to set/get the attribute name. With the same functions, all these classes can now, for example, set binary values for their contents.
class XMLVariable : public XMLContent
{
private:
string n;
bool tmp = false;
public:
explicit XMLVariable();
explicit XMLVariable(const char* nn,const char* vv,bool Temp = false);
explicit XMLVariable::XMLVariable(const XMLVariable& h);
XMLVariable& operator =(const XMLVariable& h);
// XMLVariable& operator =(const std::initializer_list<string>& s);
const string& SetName(const char* VN);
const string& SetName(const string& VN);
void Clear();
XMLVariable& operator =(const char* s);
XMLVariable& operator =(const string& s);
// Compare
bool operator <(const XMLVariable& x) const;
bool operator ==(const XMLVariable& x) const;
bool operator ==(const char* x) const;
// Gets
const string& XMLVariable::GetName() const;
// Memory usage
size_t MemoryUsage() const;
// Serialization
virtual string Serialize(bool NoEnc = false) const;
};
XMLHeader
The XML header class contains the standalone, version and encoding as attributes, so you can access them via XMLVariable
.
XMLElement
XMLElement
features:
shared_ptr
arrays of all child elements, contents, comments, cdatas, attributes.vector<shared_ptr<XMLElement>> v = el.GetChildren();
- Access to elements via operator
[]
and an index:el[0].vv["animal"] = "rabbit";
- Access via operator
[]
and astring
, creates children if they do not exist:el["hello"]["there"] = "<there v=\"test\">";
- Access to attributes via
v()
with index or variable name, or withvv()
for the fullXMLVariable
:string g = el.v("t");
- Copy or mirror:
XMLElement e1 = "<e v=\"hi\">"; XMLElement e2 = e1; XMLElement e3 = e1.Mirror(); e1.vv("v") = "hello"; // e3 variable is changed as well, e2 still "hi"
- Access to parent using
XMLId
:class XMLElement { private: string el = "e"; vector<shared_ptr<XMLElement>> children; vector<shared_ptr<XMLVariable>> variables; vector<shared_ptr<XMLContent>> contents; vector<shared_ptr<XMLComment>> comments; vector<shared_ptr<XMLCData>> cdatas; unsigned long long param = 0; XMLId parent = 0; XMLId id; static void CloneMirror(XMLElement& to,const XMLElement& from); public: XMLElement(); XMLElement(const char*); XMLElement(const XMLElement&); XMLElement(XMLElement&&); XMLElement Mirror() const; const vector<shared_ptr<XMLComment>>& XMLElement::GetComments() const { return comments; } const vector<shared_ptr<XMLElement>>& XMLElement::GetChildren() const { return children; } const vector<shared_ptr<XMLVariable>>& XMLElement::GetVariables() const { return variables; } const vector<shared_ptr<XMLCData>>& XMLElement::GetCDatas() const { return cdatas; } const vector<shared_ptr<XMLContent>>& XMLElement::GetContents() const { return contents; } vector<shared_ptr<XMLComment>>& XMLElement::GetComments() { return comments; } vector<shared_ptr<XMLElement>>& XMLElement::GetChildren() { return children; } vector<shared_ptr<XMLVariable>>& XMLElement::GetVariables() { return variables; } vector<shared_ptr<XMLCData>>& XMLElement::GetCDatas() { return cdatas; } vector<shared_ptr<XMLContent>>& XMLElement::GetContents() { return contents; } // Operators bool operator==(const XMLElement& t) const; bool operator <(const XMLElement& x) const; XMLElement& operator =(const char*); // Gets XMLElement& operator [](size_t idx); XMLElement& operator [](const char* elm); const string& v(size_t idx) const; const string& v(const char* nn); string vd(const char*nn,const char*def = 0); string vd(const char*nn,const char*def = 0) const; string Content() const; XMLVariable& vv(const char* nn); unsigned long long GetElementParam() const; const string& GetElementName() const; void GetAllChildren(vector<shared_ptr<XMLElement>>& ch) const; shared_ptr<XMLElement> GetParent(shared_ptr<XMLElement> r) const; XMLElement* GetParent(XMLElement* r) const; size_t GetElementIndex(const XMLElement& e) const; // Sets void SetElementName(const char* x); void SetElementName(const wchar_t* x); void SetElementParam(unsigned long long p); void SortElements(std::function<bool(const shared_ptr<XMLElement>&e1, const shared_ptr<XMLElement>&e2)>); void SortVariables(std::function<bool(const shared_ptr<XMLVariable>&e1, const shared_ptr<XMLVariable>&e2)>); XML_ERROR XMLElement::MoveElement(size_t i,size_t y); // Find shared_ptr<XMLElement> FindElementZ(const char* n,bool ForceCreate = false); shared_ptr<XMLVariable> FindVariableZ(const char* n,bool ForceCreate = false, const char* defv = ""); shared_ptr<XMLVariable> FindVariable(const char* n) const; // Inserts shared_ptr<XMLElement> InsertElement(size_t y,const XMLElement& x); shared_ptr<XMLElement> InsertElement(size_t y,XMLElement&& x); XMLElement& AddElement(const XMLElement& c); XMLElement& AddElement(XMLElement&& c); XMLElement& AddElement(const char* n = ""); void AddElements(const std::initializer_list<string>& s); void SetVariables(const std::initializer_list<string>& s); XMLVariable& AddVariable(const char* vn = "n",const char* vv = "v",size_t p = -1); XMLVariable& AddVariable(const XMLVariable& v,size_t p = -1); XMLContent& AddContent(const char* pv,size_t ep,size_t p = -1); XMLComment& AddComment(const char* pv,size_t ep,size_t p = -1); XMLCData& AddCData(const char* pv,size_t ep,size_t p = -1); // Removals size_t RemoveAllElements(); size_t RemoveElement(size_t i); shared_ptr<XMLElement> RemoveElementAndKeep(size_t i) throw(XML_ERROR); void clear(); // Variables size_t RemoveAllVariables(); size_t RemoveVariable(size_t i); shared_ptr<XMLVariable> RemoveVariableAndKeep(size_t i) throw (XML_ERROR); string EorE(const string& s,bool N) const; string Serialize(bool NoEnc = false,size_t deep = 0) const; void Serialize(string& v,bool NoEnc = false,size_t deep = 0) const; };
XML
- Construct empty, from ansi/unicode file, from memory.
- Save to memory, file or FILE*.
- operator = to parse text.
- Contains an
XMLHeader
, anXMLDocType
, a vector ofXMLComment
and the rootXMLElement
.
class XML
{
private:
bool UnicodeFile = false;
string fname;
XMLHeader hdr;
XMLDocType doctype;
vector<shared_ptr<XMLComment>> hdrcomments;
XMLElement root;
public:
// Constructors
XML();
XML(const char* file);
XML(const wchar_t* file);
XML(const char* mem,size_t l);
void operator =(const char* d);
// Savers
size_t SaveFP(FILE* fp) const;
XML_ERROR Save() const;
XML_ERROR Save(const char* f) const;
XML_ERROR Save(const wchar_t* f) const;
// Loaders
XML_PARSE ParseFile(FILE* fp);
XML_PARSE Load(const char* f);
XML_PARSE Load(const wchar_t* f);
XML_PARSE Parse(const char* m,size_t len);
// Gets
XMLElement& XML::GetRootElement();
XMLHeader& XML::GetHeader();
size_t XML::MemoryUsage();
// Sets
void SetRootElement(XMLElement& newroot);
void SetHeader(const XMLHeader& h);
void Clear();
void Version(XML_VERSION_INFO* x);
// ser
string Serialize(bool NoEnc = false) const;
};
Example sample.xml
<?xml version="1.0" standalone="yes" ?>
<!DOCTYPE catalog SYSTEM "catalog.dtd">
<!-- root comment 1 -->
<!-- root comment 2 -->
<catalog>
<!-- cat comment 1 -->
<product description="Cardigan Sweater" product_image="cardigan.jpg" >
<!-- pro comment 1 -->
<catalog_item gender="Men's">
<item_number>QWZ5671</item_number>
<price>39.95</price>
<![CDATA[
hohoho
dfsfd
^%$&^$*^*^#&^#$&^
]]>
<size description="Medium">
cont 1
<color_swatch image="red_cardigan.jpg">Red</color_swatch>
cont 2
<color_swatch image="burgundy_cardigan.jpg">Burgundy</color_swatch>
cont 3
</size>
<size description="Large">
<color_swatch image="red_cardigan.jpg">Red</color_swatch>
<color_swatch image="burgundy_cardigan.jpg">Burgundy</color_swatch>
</size>
</catalog_item>
</product>
</catalog>
Parse it:
using namespace XML3;
XML x("sample.xml");
auto&root = x.GetRootElement();
string v1 = root["product"].v(0); // Cardigan Sweater
string v2 = root["product"]["catalog_item"]["price"].GetContent(); // 39.95
string v3 = root.AddVariable("n","val").Serialize(); // created a new variable in root, n="val"
JSON
The helper XML3::JsonParser(XMLElement* r,const char* txt)
helps you parse JSON into an XMLElement
. It creates a <json>
element inside r
, and puts all JSON data there. Note that this is not a complete implementation of JSON.
History
- 04/09/2018 Prepare for canonicalization and XAdES-T
- 24/12/2015 Fixed case when
<?xml?>
in not closing the header - 04/11/2015 Fixed trimming in
XMLContent
- 29/10/2015 Removed MIME code and used Win32 API instead, also fixed GCC incompatibilities
- 19/09/2015 Fixed case when
<?xml?>
without other spaces - 31/07/2015 Simplified BXML by using
vector<char>
- 13/07/2015 Added copy + move constructor to XML
- 09/07/2015 More move semantics in
BXML
andXMLElement
- 06/07/2015 Added move semantics for
XMLElement Insert
/Add
element and fixedXMLVariable
bug. - 14/06/2015 Bugfixes and speed enhancements
- 06/06/2015 First release