2016-08-21 4 views
1

Ну вот, я снова работаю над этой игрой с открытым исходным кодом, так или иначе я сделал этот синтаксический анализатор для XML-файла, однако я не уверен, как разбирать дочерние узлы призвания, вот код и xml для функция, я хочу, чтобы иметь возможность прокручивать ее дочерние элементы, я предполагаю, что мне нужно создать другой цикл, но я не совсем уверен, как мне следует ссылаться на дочерние узлы призвания, меня не интересуют их атрибуты atm.C++ parsing sub nodes of xml

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> 

Edit 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; 
} 

Не совсем уверен, что если ребенок ребенок является законным ... а просто выбросить его там лол

Edit 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 в подобной структуре.

+0

Я предполагаю, что я мог бы просто запустить некоторые тесты и посмотреть, какой результат: p –

+0

Не нужно было запускать какие-либо тесты :) Я думаю, что у меня есть решение, которое опубликует, когда я его скомпилирую и протестирую. –

+0

Это не очень простой формат для анализа, когда у вас есть разные имена атрибутов для каждого атрибута '' nodes *. – Galik

ответ

1

Мне нравится pugixml много, что делает синтаксический анализ очень простым. Однако ваш формат XML является довольно сложным, я бы подумал о сохранении вашего <attributes> по-разному.

В настоящее время вы можете перебирать призваний и атрибуты вроде этого:

#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'; 

    } 
} 
+0

Спасибо, что вы сделали его очень простым, и у меня есть лучшее представление о том, как построить код для чего-то еще позже, спасибо снова, вы рок! –