1

I am trying to parse a file with nested maps and sequences which somewhat looks like this

annotations:
 - dodge:
   type: range based
   attributes:
    start_frame:
     frame_number: 25
     time_stamp: 2017-10-14 21:59:43
    endframe:
     frame_number: 39     
     time_stamp: 2017-10-14 21:59:45
    distances:
     - 2
     - 5
     - 6

I am getting an error saying Ensure the node exists. Below is my sample code.

YAML::Node basenode = YAML::LoadFile(filePath);

const YAML::Node& annotations = basenode["annotations"];

RangeBasedType rm;

for (YAML::const_iterator it = annotations.begin(); it != annotations.end(); ++it)
{
    const YAML::Node& gestures = *it;

    std::string type = gestures["type"].as<std::string>(); // this works

    rm.setGestureName(type);

    if (type == "range based")
    {
        const YAML::Node& attributes = gestures["attributes"];

        for (YAML::const_iterator ti = attributes.begin(); ti != attributes.end(); ++ti)
        {
            const YAML::Node& frame = *ti; 

            if (frame["start_frame"]) // this fails saying it is not a valid node
            {
                std::cout << frame["frame_number"].as<int>();

                rm.setStartFrame(frame["frame_number"].as<int>());
            }
        }
    }
}

I wish to get the frame_number from nodes start_frame and end_frame. I have checked the YAML format for validity. Any reasons on why this is not working?

2
  • 1
    It looks like this code could be simplified quite a bit by using range-based for loops. Commented Feb 1, 2018 at 17:24
  • could you please explain it briefly as how can i achieve that? Commented Feb 2, 2018 at 13:19

1 Answer 1

3

This loop:

for (YAML::const_iterator ti = attributes.begin(); ti != attributes.end(); ++ti)

is iterating over a map node. Therefore, the iterator points to a key/value pair. Your next line:

const YAML::Node& frame = *ti;

dereferences it as a node. Instead, you need to look at its key/value nodes:

const YAML::Node& key = ti->first;
const YAML::Node& value = ti->second;

yaml-cpp allows iterators to both point to nodes and key/value pairs because it can be a map or a sequence (or a scalar), and it's implemented as a single C++ type.

Sign up to request clarification or add additional context in comments.

2 Comments

It worked! Thank you Jesse. I guess i can traverse through a sequence node "distances" similarly.
I also like to use range-based loops e.g. for (auto&& mapNode : sequenceNode ) { // do something with mapNode["someKey"] }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.