以下任务: 我有一个 xml 文件,其中包含我需要处理的数据。此数据分组在以分层方式组织的各个节点中。为简单起见,我稍微减少了xml文件的结构:
<doc_root>
<case_def>
<shape number="1">
... shape data ...
</shape number>
<shape number="2">
... shape data ...
</shape number>
</case_def>
<parameters>
</parameters>
</doc_root>
此文件存储在具有特定名称的特定路径中。我的目的是稍后通过 argc 参数将其传递给 main(),但这是另一个问题。目前,我对这些信息进行硬编码很好。
现在我有一个类tXmlDoc
,它有一个方法,可以在成员变量xml_doc
中加载整个 xml 文档,该变量用作提取每个节点数据的句柄。我的类tXmlDoc
还将提取整个<doc_root>
节点,该节点本身可以用作访问节点case_def
和parameters
以及最终每个节点shape
节点的句柄。
这是tXmlDoc
的头文件:
#include <iostream>
#include <string>
#include <array>
#include "../../libs/pugixml-1.11/src/pugixml.hpp"
#include "XmlData_General.h"
#include "XmlNodes.h"
namespace nXml
{
//------------------------------------------------------
class tXmlDoc
{
public:
tXmlDoc();
~tXmlDoc();
void LoadXmlFile(const std::string& file_name, std::string& file_path);
pugi::xml_node GetRootNode();
std::string GetFileName();
std::string GetFilePath();
std::string GetFullPath(const std::string& file_name, std::string& file_path); //returns string containing the full path directly to the file
void SetFileName(const std::string& file_name);
void SetFilePath(const std::string& file_path);
bool GetFileLoaded();
int GetErrorCode();
pugi::xml_parse_result GetXmlResult();
void LoadData();
protected:
std::string file_path = ""; //is set when calling LoadXmlFile
std::string file_name = ""; //is set when calling LoadXmlFile
bool file_loaded = false; //provides information is file was successfully loaded (file correctly loaded: true). Modified by method LoadXmlFile
int error_code = 0; //provides information about occuring errors (no error: 0). Modified by method LoadXmlFile
pugi::xml_parse_result xml_result; //contains information about parsing result. Filled by method LoadXmlFile
pugi::xml_node root_node; //contains the root node of the xml document. Filled when calling LoadData (via calling GetRootNode inside LoadData)
pugi::xml_document xml_doc; //contains the entire document
}
;
};
现在为了访问和处理shape
节点中的数据,我创建了一个类tShapeNode
:
#include <iostream>
#include <string>
#include <charconv>
#include "../../libs/pugixml-1.11/src/pugixml.hpp"
#include "XmlNodes.h"
#include "tXmlDoc.h"
namespace nXml
{
class tXmlShape
{
public:
tXmlShape();
tXmlShape(const int shape_id);
~tXmlShape();
pugi::xml_node GetShapeNode(const int);
int GetShapeId();
int GetAttributNumber();
std::string GetShapeType(const int shape_id);
std::string GetDescription(const int shape_id);
void LoadData();
protected:
tXmlDoc xml_doc;
pugi::xml_node shape_node;
int shape_id = 0;
int n_attr = 0;
std::string description;
std::string shape_type;
}
;
}
;
如您所见,我已将tXmlDoc
成员添加到我的tXmlShapeNode
中,以便我可以访问tXmlShapeNode
所需的tXmlDoc
中的数据。为了访问存储在<shape>
节点中的数据,我需要doc_root
节点的句柄。所以这个想法是使用tXmlShapeNode
的构造函数将数据加载到tShapeNode
的本地tXmlDoc xml_doc
成员中。但是,我必须对 xml 文件中的每个形状执行此操作,这在内存和操作方面似乎效率不高。
现在我有两个问题:
- 如何将存储在
tXmlDoc.root_node
中的信息传递给tXmlShapeNode
,而不必为我拥有的每个形状处理 xml 文档? - 有没有办法避免全局变量将文件名和文件路径的信息传递给tXmlDoc类?
回答第 1 部分。
不要将形状类xml_doc为 tXmlDoc 对象,而是将其设置为引用实际 tXmlDoc 对象的对象
使用C++引用
// note the '&'
tXmlDoc & xml_doc;
或指针
// note the '*'
tXmlDoc * xml_doc;
任一选项都可用于访问某些远程对象,如文档类。 通常,您将把对 doc 类的引用传递给构造函数中的形状类。
在这里,构造函数使用引用:
class tXmlShape
{
public:
// tXmlShape(); //Now your constructor must include a reference, so this won't work
tXmlShape(const int id,tXmlDoc & doc) : xml_doc(doc),shape_id(id){}
//...
tXmlDoc & xml_doc;
int shape_id;
};
这里使用指针:
class tXmlShape
{
public:
// for clarity init the members in the constructor
tXmlShape(): xml_doc(nullptr),shape_id(0){}
tXmlShape(const int id,tXmlDoc * doc) : xml_doc(doc),shape_id(id){}
//...
tXmlDoc * xml_doc;
int shape_id;
};
当然,引用并非没有问题,主要是确保它们所引用的对象确实存在。这是C++的一个主要方面,在这篇文章中介绍它太复杂了,但你会发现很多关于如何处理参考文献的文献