【问题标题】:C++ parsing sub nodes of xmlC++解析xml的子节点
【发布时间】:2016-12-28 06:47:18
【问题描述】:

好吧,我又在做这个开源游戏了,无论如何我为一个 xml 文件制作了这个解析器,但是我不确定如何解析这个职业的子节点,这里是函数的代码和 xml,我想能够遍历它的子节点,我假设我需要创建另一个 for 循环,但是我不太确定我应该如何引用职业的子节点,我不关心它们的属性 atm。

bool Game::loadCreatureAdditionalAttributes()
{
    pugi::xml_document data;
    pugi::xml_parse_result result = data.load_file("data/XML/attributes.xml");
    if (!result) {
        printXMLError("Error - Game::loadCreatureAdditionalAttributes", "data/XML/attributes.xml", result);
        return false;
    }
    bool attributesEnabled = false;
    for (auto attributeNode : data.child("attributes").children()) {
        if (strcasecmp(attributeNode.name(), "additionalAttributes") == 0) {
            if (attributeNode.attribute("enabled").as_bool()) {
                if (strcasecmp(attributeNode.name(), "vocation") == 0) {
                    pugi::xml_attribute vocation = attributeNode.attribute("id");
                    uint32_t aNode;
                    pugi::xml_attribute attr = attributeNode.attribute(attributeNode.name());
                    if (attr) {
                        aNode = pugi::cast<uint32_t>(attr.value());
                    }
                    else {
                        aNode = 0;
                    }
                    CreatureAttributes[pugi::cast<uint32_t>(vocation.value())][attributeNode.name()] = aNode;
                }
            }
        }
    }
    return true;
}

现在是 xml

<?xml version="1.0" encoding="UTF-8"?>
<attributes>
    <additionalAttributes enabled = "0" />
    <vocation id = "1">
        <attribute stamina = "1" />
        <attribute strength = "1" />
        <attribute intelligence = "1" />
        <attribute dexterity = "1" />
        <attribute wisdom = "1" />
        <attribute luck = "1" />
        <attribute critical = "1" />
        <attribute block = "1" />
        <attribute experienceGain = "1" />
        <attribute power = "1" />
        <attribute precision = "1" />
    </vocation>
    <vocation id = "2">
        <attribute stamina = "1" />
        <attribute strength = "1" />
        <attribute intelligence = "1" />
        <attribute dexterity = "1" />
        <attribute wisdom = "1" />
        <attribute luck = "1" />
        <attribute critical = "1" />
        <attribute block = "1" />
        <attribute experienceGain = "1" />
        <attribute power = "1" />
        <attribute precision = "1" />
    </vocation>
</attributes>

编辑 1:

尚未对此进行测试,但我想我会根据给出的答案显示一些更新。

bool Game::loadCreatureAdditionalAttributes()
{
    pugi::xml_document data;
    pugi::xml_parse_result result = data.load_file("data/XML/attributes.xml");
    if (!result) {
        printXMLError("Error - Game::loadCreatureAdditionalAttributes", "data/XML/attributes.xml", result);
        return false;
    }

    auto attr = data.child("attributes").child("additionalAttributes");
    bool attributesEnabled = attr.attribute("enabled").as_bool();

    if (attributesEnabled) {
        for (auto vocation : data.child("attributes").children("vocation")) {
            uint32_t id = pugi::cast<uint32_t>(vocation.attribute("id").value());
            for (auto attribute : vocation.children("attribute")) {
                for (auto& a : attribute.attributes()) {
                    CreatureAttributes[id][a.name()] = pugi::cast<uint32_t>(a.value());
                }
            }
        }
    }
    return true;
}

不完全确定孩子对孩子是否合法......但只是把它扔在那里哈哈

编辑 2:

还没有测试,只是更新它,以防它不能按预期工作。

bool Game::loadCreatureAdditionalAttributes()
{
    pugi::xml_document data;
    pugi::xml_parse_result result = data.load_file("data/XML/attributes.xml");
    if (!result) {
        printXMLError("Error - Game::loadCreatureAdditionalAttributes", "data/XML/attributes.xml", result);
        return false;
    }

    auto attr = data.child("attributes").child("additionalAttributes");
    if (attr) {

        bool attributesEnabled = attr.attribute("enabled").as_bool();

        if (attributesEnabled) {
            for (auto vocation : data.child("attributes").children("vocation")) {
                uint32_t id = pugi::cast<uint32_t>(vocation.attribute("id").value());
                for (auto attribute : vocation.children("attribute")) {
                    for (auto& a : attribute.attributes()) {
                        CreatureAttributes[id][a.name()] = pugi::cast<uint32_t>(a.value());
                    }
                }
            }
            return true;
        }
    }
    return false;
}

只是想为有类似问题的人提供更新,代码效果很好!

vocation id = 1 attributes = stamina value = 1
vocation id = 1 attributes = strength value = 45
vocation id = 1 attributes = intelligence value = 1
vocation id = 1 attributes = dexterity value = 1
vocation id = 1 attributes = wisdom value = 63
vocation id = 1 attributes = luck value = 1
vocation id = 1 attributes = critical value = 1
vocation id = 1 attributes = block value = 1
vocation id = 1 attributes = experienceGain value = 1
vocation id = 1 attributes = power value = 81
vocation id = 1 attributes = precision value = 1
vocation id = 2 attributes = stamina value = 100
vocation id = 2 attributes = strength value = 1
vocation id = 2 attributes = intelligence value = 20
vocation id = 2 attributes = farfenugen value = 1
vocation id = 2 attributes = stackoverflow value = 1000

当然,我稍微更改了代码以使其可以与我正在处理的其他代码一起使用,但是Edit 2 中的示例代码可以与结构类似的 xml 文件一起正常工作。

【问题讨论】:

  • 我想我可以运行一些测试,看看输出是什么:p
  • 不必运行任何测试 :) 我想我有解决方案,我会在编译和测试时发布它。
  • 当每个&lt;attribute&gt; 节点attributes 有不同的属性名称时,这不是一个很容易解析的格式。
  • 就我个人而言,我可能会将这些&lt;attribute&gt; 节点设为&lt;vocation&gt; 节点的实际属性,例如&lt;vocation id="1" stamina="1" strength="1"... etc&gt;,或者让每个属性都有自己的标签&lt;stamina&gt;1&lt;/stamina&gt;
  • 好吧,这并没有按预期工作,为了让它工作,我必须编辑随附的 SDK,尽管我可以重载现有功能,但我不知道该怎么做我仍然是 C++ 的初学者:p

标签: c++ xml parsing


【解决方案1】:

我非常喜欢pugixml,它使解析变得非常容易。但是您的XML 格式有点棘手,我会考虑以不同的方式存储您的&lt;attributes&gt;

目前您可以像这样遍历 职业属性

#include <iostream>

#define PUGIXML_HEADER_ONLY
#include "pugixml.hpp"

auto xml = R"(
<?xml version="1.0" encoding="UTF-8"?>
<attributes>
    <additionalAttributes enabled = "0" />
    <vocation id = "1">
        <attribute stamina = "1" />
        <attribute strength = "1" />
        <attribute intelligence = "1" />
    </vocation>
    <vocation id = "2">
        <attribute stamina = "1" />
        <attribute strength = "1" />
        <attribute intelligence = "1" />
    </vocation>
</attributes>
)";

int main()
{
    pugi::xml_document doc;

    doc.load(xml);

    for(auto vocation: doc.child("attributes").children("vocation"))
    {
        std::cout << "vocation id:" << vocation.attribute("id").as_string() << '\n';

        for(auto attribute: vocation.children("attribute"))
        {
            for(auto& a: attribute.attributes())
            {
                std::cout << "    attribute: " << a.name() << '\n';
                std::cout << "             : " << a.value() << '\n';
            }
        }
    }
}

我可能会像这样组织我的XML

#include <iostream>

#define PUGIXML_HEADER_ONLY
#include "pugixml.hpp"

auto xml = R"(
<?xml version="1.0" encoding="UTF-8"?>
<attributes>
    <additionalAttributes enabled = "0" />
    <vocation id = "1">
        <stamina>1</stamina>
        <strength>1</strength>
        <intelligence>1</intelligence>
    </vocation>
    <vocation id = "2">
        <stamina>1</stamina>
        <strength>1</strength>
        <intelligence>1</intelligence>
    </vocation>
</attributes>
)";

int main()
{
    pugi::xml_document doc;

    doc.load(xml);

    for(auto vocation: doc.child("attributes").children("vocation"))
    {
        std::cout << "vocation id:" << vocation.attribute("id").as_string() << '\n';
        std::cout << "           : stamina = " << vocation.child("stamina").text().as_string() << '\n';
        std::cout << "           : strength = " << vocation.child("strength").text().as_string() << '\n';
        std::cout << "           : intelligence = " << vocation.child("intelligence").text().as_string() << '\n';
        std::cout << '\n';

    }
}

【讨论】:

  • 谢谢你让它看起来很简单,我对如何为其他东西构建代码有了更好的想法,再次感谢,你摇滚!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多