Boost读写xml

Boost读写xml

文章目录

写在前面

​ 前面我们讲过了如何使用Boost读写ini文件,这一篇我们将介绍如何用Boost读写xml文件。

​ XML (Extensible Markup Language) 是一种通用的数据描述语言,它提供了一种独立于平台和编程语言的方式来存储和交换结构化数据。XML 文件采用标签的形式描述数据,使得数据具有自我描述的特点,更易于理解和管理。XML 广泛应用于各种领域,如 Web 开发、配置管理、数据交换等,它支持数据验证、数据转换等功能,并提供了丰富的编程接口,方便开发人员在应用程序中解析和操作 XML 数据。

准备工作

  • 需要用到的头文件
cpp 复制代码
#include <boost/property_tree/xml_parser.hpp>
#include <boost/property_tree/ptree.hpp>

简单读写

  • Boost中读写xmlini文件都是使用property_tree来完成的,所以大部分东西是通用的。
  • 需要注意的是ini文件没有节点嵌套,所有节点都在根节点下的一级节点,xml是有多级节点的,且允许多级嵌套,但根节点只有一个。
  • 下面将展示简单的xml文件的读写功能,进阶用法请看具有属性的xml

写xml

cpp 复制代码
void write_xml_file_test() {
    using	boost::property_tree::ptree;

	ptree root;	// 创建根节点

	ptree student_pt;
	student_pt.put<std::string > ("Name", "Xiao Ming");
	student_pt.put<uint8_t>("Age", 15);
	student_pt.put<std::string>("Sex", "man");
	student_pt.put<uint8_t>("Class", 1);

	root.add_child("XmlTest.Student", student_pt);	// 将子节点添加到根节点中
	// 添加setting 确保输出文件内容有缩进
	auto setting = boost::property_tree::xml_writer_make_settings<std::string>('\t', 1);
	write_xml("example2.xml", root, std::locale(), setting);
}
xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<XmlTest>
	<Student>
		<Name>Xiao Ming</Name>
		<Age>15</Age>
		<Sex>man</Sex>
		<Class>1</Class>
	</Student>
</XmlTest>

读xml

键值查找
cpp 复制代码
void read_xml_from_key(std::string fileName) {
	using	boost::property_tree::ptree;
	ptree root;
	read_xml(fileName, root);
	
	// 这里的root是根节点,想要直接访问元素,需要全名称描述(XmlTest.Student.Name)
	// 键值查找,如果键不存在,则触发异常
	std::string st_name = root.get<std::string>("XmlTest.Student.Name");	
	int st_age = root.get<int>("XmlTest.Student.Age");
	std::string st_sex = root.get<std::string>("XmlTest.Student.Sex");
	int st_class = root.get<int>("XmlTest.Student.Class");

	std::cout << "Name: " << st_name << std::endl;
	std::cout << "Age: " << st_age << std::endl;
	std::cout << "Sex: " << st_sex << std::endl;
	std::cout << "Class: " << st_class << std::endl;

	// student_node节点下是Student的元素,可直接获取(Name)
	ptree student_node = root.get_child("XmlTest.Student");  // 获取 Student 子节点
	st_name = student_node.get<std::string>("Name");
	std::cout << "Name: " << st_name << std::endl;
}

/* output:
Name: Xiao Ming
Age: 15
Sex: man
Class: 1
Name: Xiao Ming
*/
遍历
cpp 复制代码
void read_xml_file_text(std::string fileName) {
	using	boost::property_tree::ptree;
	ptree root;
	read_xml(fileName, root);
	ptree student_node(root.get_child("XmlTest.Student"));	// 获取 Student 子节点

	// 遍历子节点
	std::cout << "method 1:\n";
	for (ptree::iterator it = student_node.begin(); it != student_node.end(); ++it) {
		std::cout << "\t" << it->first;
		std::cout << ":" << it->second.data() << std::endl;
	}
	std::cout << "method 2:\n";
	for (const auto &t : student_node) {
		std::cout << "\t" << t.first;
		std::cout << ":" << t.second.data() << std::endl;
	}
}

/* output:
method 1:
        Name:Xiao Ming
        Age:15
        Sex:man
        Class:1
method 2:
        Name:Xiao Ming
        Age:15
        Sex:man
        Class:1
*/

设置默认值

  • property_tree设置默认的方式是一样的,我们在Boost读写ini文件中已经说明过了。

    cpp 复制代码
    // 获取当前节点不存在的节点时,无默认值,引发程序异常
    int st_heigh = student_node.get<int>("Height");
    // 获取当前节点不存在的节点时,有默认值,不会引发异常
    int st_heigh = student_node.get<int>("Height",175);

异常处理

  • 读写xml异常一般有以下几种:

    • 读取文件不存在
    • 读取节点、属性等不存在
    • 属性内容转换失败
  • 最简单的方式是使用 std::exception 捕获所有的异常,但不利于异常分开处理

cpp 复制代码
try{
	...    
	int st_heigh = student_node.get<int>("Height"); // 引发异常
    ...    
}
catch (const boost::property_tree::ptree_bad_path& e) {			//无法访问节点异常
    std::cerr << "Node access error: " << e.what() << std::endl;
}
catch (const boost::property_tree::xml_parser_error& e) {		// 语法错误异常
    std::cerr << "XML parsing error: " << e.what() << std::endl;
}
catch (std::exception &e) {	
    std::cerr << e.what() << "\n";
}
/* output:
No such node (Height)
*/

具有属性的xml

  • xml文件除了多级节点外,每个节点、元素都可以设置属性值,类似于以下这种,一个元素可有多个属性。

    xml 复制代码
    <Name type="string">Xiao xiao</Name>
  • 属性值必须被引号包围,单双引号都可,更多详细的关于xml的文件格式可参考知识补充

写xml

cpp 复制代码
void write_xml_has_property(std::string fileName) {
	using	boost::property_tree::ptree;
	ptree root;
   
	// 创建Student 子节点
	ptree student_node;
	student_node.put<std::string>("Name", "Xiao xiao");
	student_node.put("Name.<xmlattr>.type", "string");
	student_node.put<int>("Age",  16);
	student_node.put("Age.<xmlattr>.type", "int");
	student_node.put<std::string>("Sex", "man");
	student_node.put("Sex.<xmlattr>.type", "string");
	student_node.put<int>("Class", 1);
	student_node.put("Class.<xmlattr>.type", "int");
	root.add_child("XmlTest.Student",student_node);

	auto setting = boost::property_tree::xml_writer_make_settings<std::string>('\t', 1);
	write_xml(fileName, root, std::locale(), setting);
}
xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<XmlTest>
	<Student>
		<Name type="string">Xiao xiao</Name>
		<Age type="int">16</Age>
		<Sex type="string">man</Sex>
		<Class type="int">1</Class>
	</Student>
</XmlTest>

读xml

键值查找
cpp 复制代码
void read_xml_has_property(std::string fileName) {
	try {
		using	boost::property_tree::ptree;
		ptree root_node;
		read_xml(fileName, root_node);

		ptree student_node(root_node.get_child("XmlTest.Student"));

		std::string st_name = student_node.get<std::string>("Name");
		std::string st_name_type = student_node.get<std::string>("Name.<xmlattr>.type");
		int st_age = student_node.get<int>("Age");
		std::string st_age_type = student_node.get<std::string>("Age.<xmlattr>.type");
		std::string st_sex = student_node.get<std::string>("Sex");
		std::string st_sex_type = student_node.get<std::string>("Sex.<xmlattr>.type");
		int st_class = student_node.get<int>("Class");
		std::string st_class_type = student_node.get<std::string>("Class.<xmlattr>.type");

		std::cout << "Name: "<<st_name_type<<" "<< st_name << std::endl;
		std::cout << "Age: " << st_age_type << " " << st_age << std::endl;
		std::cout << "Sex: " << st_sex_type << " " << st_sex << std::endl;
		std::cout << "Class: " << st_class_type << " " << st_class << std::endl;
	}
	catch (std::exception &e) {
		std::cerr << e.what() << "\n";
	}
}

/* output:
Name: string Xiao xiao
Age: int 16
Sex: string man
Class: int 1
*/
遍历
cpp 复制代码
void read_xml_has_property2(std::string fileName) {
	try {
		using	boost::property_tree::ptree;
		ptree root_node;
		read_xml(fileName, root_node);
        
		ptree student_node(root_node.get_child("XmlTest.Student"));
		// 遍历 Student节点和属性
		for (const auto &t : student_node) {
			std::cout << t.first << ": " <<
				t.second.get<std::string >("<xmlattr>.type") << " "<<
				t.second.data() << "\n";
		}
	}
	catch (std::exception &e) {
		std::cerr << e.what() << "\n";
	}
}

/* output:
Name: string Xiao xiao
Age: int 16
Sex: string man
Class: int 1
*/

知识补充

  • 这里对xml语法进行一个简要介绍

  • xml文件语法类似于HTML文件格式通过标签表示节点或者元素。

    xml 复制代码
    <a>name</a>
  • 允许多层嵌套,可设置属性对元素进行描述。

  • 更多详细可参考网络上的xml文件格式等。

  • XML 语法

相关推荐
小百菜10 小时前
dom4j实现xml转map,xml转json字符串
xml·json·xml转map·xml转json
玄客)12 小时前
XML标记语言
xml
 嘘 1 天前
文件操作:Xml转Excel
xml·python·excel
q567315231 天前
使用 Python 编辑 XML 文件中的文本字段
xml·java·数据库·python·sqlite
爱敲代码的小冰1 天前
java mapper 的 xml讲解
xml·java·mybatis
子非鱼9212 天前
【Ajax】原生Ajax与jQuery中的Ajax
xml·ajax·node.js·jquery
天天进步20152 天前
X2JS: XML与JSON的完美转换工具
xml·json
法迪3 天前
解读JobScheduler的jobs.xml
xml·功耗
残花月伴3 天前
配置文件格式(xml、properties、yml/yaml)
xml·java
zhangxiang_ouc3 天前
Caché/IRIS file2Xml 一个将文件转换成Studio导出的xml格式的工具
xml