65.9K
CodeProject 正在变化。 阅读更多。
Home

XML++ 版本 3:我的 XML 库的 C++11 更新

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.90/5 (33投票s)

2015 年 6 月 12 日

CPOL

2分钟阅读

viewsIcon

82991

downloadIcon

1497

我对心爱的库的更新。 单头文件。

引言

我的流行的 XML 库(https://codeproject.org.cn/Articles/18732/XML-Include-a-Flexible-Parser-in-Your-C-Applicatio)的 C++11 版本,具有更简洁的接口,包含在一个 .h 文件中,也可以用于预编译头。

BXML

一个用于在 XML 中表示二进制数据的类。 可以从 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

  • 构造函数可以从以下内容初始化
    • XMLContent v("n");
    • 另一个变量
      XMLContent v2 = v;
  • 增强功能
    • 设置值
      v2 = "hello";
    • 二进制内容
      v2.SetBinaryData("\0\0\0",3);
    • operator const char*()
      string z = v2;
  • 用于设置和获取的模板
    • v3.SetFormattedValue<int>("%d",5);
    • v3.SetFormattedValue<const char*>("%s","hello");
    • auto j = v3.GetFormattedValue<int>("%d"); // 使用 sscanf,j = int。
  • 序列化为 string,有或没有编码。
    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 和 XMLVariable/XMLAttribute

所有这些都继承自 XMLContent。 此外,XMLVariable 包含用于设置/获取属性名称的方法。 借助相同的函数,所有这些类现在都可以,例如,为其内容设置二进制值。

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

XML 头类包含独立、版本和编码作为属性,因此可以通过 XMLVariable 访问它们。

XMLElement

XMLElement 特性

  • 所有子元素、内容、注释、CDATA、属性的 shared_ptr 数组。
    vector<shared_ptr<XMLElement>> v = el.GetChildren();
  • 通过运算符 [] 和索引访问元素
    el[0].vv["animal"] = "rabbit";
  • 通过运算符 []string 访问,如果它们不存在则创建子元素
    el["hello"]["there"] = "<there v=\"test\">";
  • 通过索引或变量名使用 v() 访问属性,或使用 vv() 访问完整的 XMLVariable
    string g = el.v("t");
  • 复制或镜像
    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"
  • 使用 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

  • 构造空元素,从 ansi/unicode 文件,从内存构造。
  • 保存到内存、文件或 FILE*。
  • operator = 用于解析文本。
  • 包含一个 XMLHeader、一个 XMLDocType、一个 XMLComment 向量和根 XMLElement
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;

    };

示例 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>

解析它

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

helper XML3::JsonParser(XMLElement* r,const char* txt) 帮助您将 JSON 解析到 XMLElement 中。 它在 r 内部创建一个 <json> 元素,并将所有 JSON 数据放在那里。 请注意,这并不是 JSON 的完整实现。

历史

  • 2018/09/04 准备用于规范化和 XAdES-T
  • 2015/12/24 修复了 <?xml?> 未关闭头的情况
  • 2015/11/04 修复了 XMLContent 中的修剪问题
  • 2015/10/29 删除了 MIME 代码,并使用了 Win32 API,还修复了 GCC 不兼容问题
  • 2015/09/19 修复了 <?xml?> 没有其他空格的情况
  • 2015/07/31 通过使用 vector<char> 简化了 BXML
  • 2015/07/13 为 XML 添加了复制 + 移动构造函数
  • 2015/07/09 在 BXMLXMLElement 中添加了更多移动语义
  • 2015/07/06 为 XMLElement Insert/Add 元素添加了移动语义,并修复了 XMLVariable 错误。
  • 2015/06/14 错误修复和速度增强
  • 2015/06/06 首次发布
© . All rights reserved.