避免C+的冗余映射+;程序 这是我的C++代码,它的意思是做如下:< /P> 比较一组XML文件,看看它们之间有什么不同 如果节点是新的,则转储它(在B.xml中,但不是在A.xml中) 扫描该节点并使用map将标记与信息类型关联 根据数据的类型处理数据

避免C+的冗余映射+;程序 这是我的C++代码,它的意思是做如下:< /P> 比较一组XML文件,看看它们之间有什么不同 如果节点是新的,则转储它(在B.xml中,但不是在A.xml中) 扫描该节点并使用map将标记与信息类型关联 根据数据的类型处理数据,c++,xml,c++11,xml-parsing,C++,Xml,C++11,Xml Parsing,我对第1-2步的工作方式很满意,但是第3-4步我觉得我可能执行得很差。我主要关心的是,即使已经匹配了标记(如id),我也必须映射标记,而实际上,只有当映射不同(如描述)时,才最好定义一个映射 我的代码: #include "pugi/pugixml.hpp" #include <iostream> #include <string> #include <map> int main() { // This map relates the type

我对第1-2步的工作方式很满意,但是第3-4步我觉得我可能执行得很差。我主要关心的是,即使已经匹配了标记(如id),我也必须映射标记,而实际上,只有当映射不同(如描述)时,才最好定义一个映射

我的代码:

#include "pugi/pugixml.hpp"

#include <iostream>
#include <string>
#include <map>

int main()
 {
    // This map relates the type of content to the tag name in the XML file
    const std::map<std::string, std::string> tagMap {
         {"id", "id"}, {"description", "content"}, {"url", "web_address"}, {"location", "location"}
     };

    pugi::xml_document doca, docb;
     std::map<std::string, pugi::xml_node> mapa, mapb;

    for (auto& node: doca.child("data").children("entry")) {
     const char* id = node.child_value("id");
     mapa[id] = node;
     }

    for (auto& node: docb.child("data").children("entry")) {
     const char* idcs = node.child_value("id");
         if (!mapa.erase(idcs)) {
         mapb[idcs] = node;
         }
     }

    // For added nodes
     for (auto& eb: mapb) {
         // Loop through Tag map to see if we can find tags named "id, content, web_address or location" in the node returned
         for (auto& kv : tagMap) {
         // For each result, assign the value of that tag to the type of content
         // For example: description = Testing!
         kv.first = eb.second.child_value(kv.second.c_str());
         // If it's an ID...
             if (kv.first == "id") {
             // Do work on ID value (i.e check if it's unique)
             }
             if (kv.first == "description") {
            // Do work on Description data (I.e Trim it)
             }
             if (kv.first == "url") {
             // Do work on URL data (I.e validate it)
             }
             if (kv.first == "location") {
             // Do work on location data
             }
         }
     }

}
#包括“pugi/pugixml.hpp”
#包括
#包括
#包括
int main()
{
//此映射将内容类型与XML文件中的标记名相关联
const std::map标记映射{
{“id”,“id”},{“description”,“content”},{“url”,“web_address”},{“location”,“location”}
};
pugi::xml_文档doca,docb;
标准::map mapa,mapb;
用于(自动和节点:doca.child(“数据”).children(“条目”)){
const char*id=node.child_值(“id”);
mapa[id]=节点;
}
用于(自动和节点:docb.child(“数据”).children(“条目”)){
const char*idcs=node.child_值(“id”);
如果(!mapa.erase(idcs)){
mapb[idcs]=节点;
}
}
//对于添加的节点
用于(自动和eb:mapb){
//循环遍历标记映射,查看是否可以在返回的节点中找到名为“id、内容、web\u地址或位置”的标记
用于(自动和kv:tagMap){
//对于每个结果,将该标记的值指定给内容类型
//例如:描述=测试!
kv.first=eb.second.child_值(kv.second.c_str());
//如果是身份证。。。
如果(千伏第一==“id”){
//处理ID值(即检查其是否唯一)
}
如果(kv.first==“说明”){
//处理描述数据(即修剪)
}
如果(kv.first==“url”){
//处理URL数据(即验证它)
}
如果(kv.first==“位置”){
//处理位置数据
}
}
}
}
输入文件示例:


1.
描述
www.google.com
英格兰
试验
试验
..

我对您的第3点和第4点有两种不同的改进:

  • 简单的改进:
  • 作为
    标记映射的键
    使用枚举,例如

    enum Tags { Tag_ID, Tag_Description, ... }
    
    这避免了字符串比较

  • 一种更动态的方法是使用多态性
  • 定义抽象基类
    标记

    class Tag {
    public:
        virtual const char* getTagname() const = 0;
        virtual void processNode(const std::string& value) = 0;
    };
    
    然后为每个标记实现一个子类

    class IdTag : public Tag {
    public:
        const char* getTagname() const { return "Id"; }
        void processNode(const std::string& value) { /* Do something */ }
    };
    
    现在您可以使用标记列表<代码>标准::列表标记映射{new IdTag(),new DescriptionTag(),…}

    您的新循环:

    // For added nodes
     for (auto& eb: mapb) {
         // Loop through Tag map to see if we can find tags named "id, content, web_address or location" in the node returned
         for (auto& kv : tagMap) {
             kv->processNode(eb.second.child_value(kv->getTagname());
         }
     }
    

    我投票结束这个问题,因为这个问题属于@Barry,我刚被告知把它移到这里谢谢你的回答。关于您的示例,我不了解的是,如何将枚举与内容关联起来。例如,定义“content”是一个标记已经足够公平了,但是我如何说content标记是一个描述呢?您可以使用与代码中相同的循环。枚举只是替换字符串。