2016-08-21 4 views
1

Nun, ich arbeite wieder an diesem Open-Source-Spiel, trotzdem habe ich diesen Parser für eine XML-Datei gemacht, aber ich bin unsicher, wie die Kinder Knoten der Berufung zu analysieren, hier ist der Code und das Xml für die Funktion, ich möchte in der Lage sein, durch seine Kinder zu durchlaufen, ich nehme an, dass ich eine andere for-Schleife erstellen muss, aber ich bin nicht ganz sicher, wie ich die Kindknoten der Berufung referenzieren sollte, ich bin nicht mit ihren Attributen beschäftigt.C++ Parsing Sub-Knoten von 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; 
} 

Und nun die 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:

Lassen Sie sich diese nur noch nicht getestet, aber ich dachte, dass ich ein Update zeigen würde basierend etwas auf die gegebene Antwort.

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

Nicht ganz sicher, ob Kind zu Kind legal ist ... aber es gerade dort wirft lol

Edit 2:

Noch habe es noch nicht getestet, nur um es bei der Aktualisierung Es funktioniert nicht wie erwartet.

Ich wollte nur ein Update für diejenigen mit ähnlichen Problemen geben, der Code funktioniert super!

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 

Natürlich änderte ich den Code ein wenig, um es mit anderem Code funktioniert arbeite ich an, aber das Codebeispiel in Edit 2 wird mit einer XML-Datei in der Struktur ähnlich funktionieren.

+0

Ich glaube, ich nur laufen konnte einige Tests und sehen, was die Ausgabe ist: p –

+0

musste keine Tests ausführen :) Ich denke, ich habe die Lösung, die es wird, wenn ich es kompilieren und testen. –

+0

Das ist kein sehr einfaches zu analysierendes Format, wenn Sie für jedes '' Knoten * Attribute * unterschiedliche Attributnamen haben. – Galik

Antwort

1

Ich mag pugixml viel es macht das Parsen sehr einfach. Aber Ihr XML Format ist irgendwie knifflig, würde ich in Betracht ziehen, Ihre <attributes> anders zu speichern.

Aktuell können Sie durch die Berufungen iterieren und die Attribute wie folgt aus:

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

würde ich wahrscheinlich meine organisieren XML mehr wie folgt aus:

#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

Danke, dass du es so einfach gemacht hast und ich habe eine bessere Idee, wie ich später den Code für etwas anderes konstruiere, danke nochmal, du rockst! –