首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

C+实现xml解析器

xml格式简单介绍

"1.0"?>

name="1" switch="on">

name="echoplugin.so" switch="on" />

复制代码

我们来简单观察下上面的xml文件,xml格式和html格式十分类似,一般用于存储需要属性的配置或者需要多个嵌套关系的配置。

xml一般使用于项目的配置文件,相比于其他的ini格式或者yaml格式,它的优势在于可以将一个标签拥有多个属性,比如上述xml文件格式是用于配置工作流的,其中有name属性和switch属性,且再work标签中又嵌套了plugin标签,相比较其他配置文件格式是要灵活很多的。

具体的应用场景有很多,比如使用过Java中Mybatis的同学应该清楚,Mybatis的配置文件就是xml格式,而且也可以通过xml格式进行sql语句的编写,同样Java的maven项目的配置文件也是采用的xml文件进行配置。

而我为什么要写一个xml解析器呢?很明显,我今后要写的C++项目需要用到。

xml格式解析过程浅析

同样回到之前的那段代码,实际上已经把xml文件格式的不同情况都列出来了。

从整体上看,所有的xml标签分为:

xml声明(包含版本、编码等信息)

注释

xml元素:1.单标签元素。 2.成对标签元素。

其中xml声明和注释都是非必须的。 而xml元素,至少需要一个成对标签元素,而且在最外层有且只能有一个,它作为根元素。

从xml元素来看,分为:

名称

属性

内容

子节点

根据之前的例子,很明显,名称是必须要有的而且是唯一的,其他内容则是可选。 根据元素的结束形式,我们把他们分为单标签和双标签元素。

代码实现

完整代码仓库:xml-parser

实现存储解析数据的类——Element

代码如下:

namespace xml

{

using std::vector;

using std::map;

using std::string_view;

using std::string;

class Element

{

public:

using children_t = vector;

using attrs_t = map;

using iterator = vector::iterator;

using const_iterator = vector::const_iterator;

string &Name()

{

return m_name;

}

string &Text()

{

return m_text;

}

//迭代器方便遍历子节点

iterator begin()

{

return m_children.begin();

}

[[nodiscard]] const_iterator begin() const

{

return m_children.begin();

}

iterator end()

{

return m_children.end();

}

[[nodiscard]] const_iterator end() const

{

return m_children.end();

}

void push_back(Element const &element)//方便子节点的存入

{

m_children.push_back(element);

}

string &operator[](string const &key) //方便key-value的存取

{

return m_attrs[key];

}

string to_string()

{

return _to_string();

}

private:

string _to_string();

private:

string m_name;

string m_text;

children_t m_children;

attrs_t m_attrs;

};

}

复制代码

上述代码,我们主要看成员变量。

我们用string类型表示元素的name和text

用vector嵌套表示孩子节点

用map表示key-value对的属性

其余的方法要么是Getter/Setter,要么是方便操作孩子节点和属性。 当然还有一个to_string()方法这个待会讲。

关键代码1——实现整体的解析

关于整体结构我们分解为下面的情形:

代码如下:

Element xml::Parser::Parse()

{

while (true)

{

char t = _get_next_token();

if (t != '

{

THROW_ERROR("invalid format", m_str.substr(m_idx, detail_len));

}

//解析版本号

if (m_idx + 4 < m_str.size() && m_str.compare(m_idx, 5, ") == 0)

{

if (!_parse_version())

{

THROW_ERROR("version parse error", m_str.substr(m_idx, detail_len));

}

continue;

}

//解析注释

if (m_idx + 3 < m_str.size() && m_str.compare(m_idx, 4, "

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20230206A0014U00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券