code_fodder code_fodder - 2 months ago 30
C++ Question

yaml-cpp trouble parsing mixed array/string nodes

I have the following yaml script that I have tested here: online yaml parser

testcases:
- testcase:
desc: 'TEST TC1'
requirement-ref: Doors-10.1.1.0
given:
text: 'A UUT, TEST2 and TEST are connected'
devices:
- Device:
Type: UUT
Status: Connected
- Device:
Type: TEST
Status: Connected
- Device:
Type: TEST2
Status: Connected

- testcase: # next test case...
desc: 'TEST TC2'


Then I have the following code:

#include <iostream>
#include <unistd.h>
#include <ctime>
#include "yaml-cpp/yaml.h"

using namespace std;

void load_config()
{
cout << "loading yaml file\n";

YAML::Node testfile = YAML::LoadFile("BDD-test-case.yaml");
if (testfile["testcases"])
{
cout << "found testfile[\"testcases\"] - size: " << testfile["testcases"].size() << "\n";
YAML::Node testcases = testfile["testcases"];

for (int i = 0; i < testcases.size(); i++)
{
YAML::Node testcase = testcases[0];
cout << "testcase " << i << ":\n";
cout << "\tsize:" << testcase.size() << "\n";
cout << "\tIsNull:" << testcase.IsNull() << "\n";

YAML::Node desc = testcase["desc"];
if (desc)
{
std::string desc_str = desc.as<std::string>();
cout << "desc: " << desc_str.c_str() << "\n";
}
}
}
cout << "yaml - done\n";
}

int main(int argc, char *argv[])
{
long double lastTimeMS = time(0)*1000;
long double CurrTimeMS = time(0)*1000;
int localPort = 31010;
int remotePort = 31011;
int procId = 1;

load_config();

cout << "Hello World!" << endl;
return 0;
}


I get the following output:

loading yaml file
found testfile["testcases"] - size: 2
testcase 0:
size:1
IsNull:0
testcase 1:
size:1
IsNull:0
yaml - done
Hello World!


I am trying to parse through each testcase and print out the value of "desc" field.

As you can see from the debug I am able to find the top level node
testcases
. I check its size and it is 2 - which is correct. Then I loop through the testcases and store each as a new node
testcase = testcases[i]
. So far so good. However now I want to see what is inside each testcase - I should find a tsetcase["desc"]... but I don't see that. Infact testcase seems to be null...

What am I doing wrong here?

Answer

When you look up:

YAML::Node desc = testcase["desc"];

You're trying to look for the desc key in the following node:

testcase:
  desc: 'TEST TC1'
  requirement-ref: Doors-10.1.1.0
  given:
    text: 'A UUT, TEST2 and TEST are connected'
    devices:
    - Device:
        Type: UUT
        Status: Connected
    - Device:
        Type: TEST
        Status: Connected
    - Device:
        Type: TEST2
        Status: Connected

But this node has a top-level map key testcase. You probably didn't intend this; I think if you simply remove that key, then your doc will look like you're intending.

Update

The fixed YAML (removed the extra level of 'tags' that are not intended):

testcases:
-   desc: 'TEST TC1'
    requirement-ref: Doors-10.1.1.0
    given:
      text: 'A UUT, TEST2 and TEST are connected'
      devices:
      -   Type: UUT
          Status: Connected
      -   Type: TEST
          Status: Connected
      -   Type: TEST2
          Status: Connected

-   desc: 'TEST TC2'