My favorites | Sign in
Project Home Downloads Wiki Issues Source
Search
for
HowToParseADocument  
This outlines the basic methods for parsing a YAML document.
Featured
Updated Nov 12, 2011 by jbe...@gmail.com

Contents

Basic Parsing

The parser accepts streams, not file names, so you need to first load the file. Since a YAML file can contain many documents, you can grab them one-by-one. A simple way to parse a YAML file might be:

#include <fstream>
#include "yaml-cpp/yaml.h"

int main()
{
    std::ifstream fin("test.yaml");
    YAML::Parser parser(fin);

    YAML::Node doc;
    while(parser.GetNextDocument(doc)) {
       // ...
    }

    return 0;
}

Reading From the Document

Suppose we have a document consisting only of a scalar. We can read that scalar like this:

YAML::Node doc;    // let's say we've already parsed this document
std::string scalar;
doc >> scalar;
std::cout << "That scalar was: " << scalar << std::endl;

How about sequences? Let's say our document now consists only of a sequences of scalars. We can use an iterator:

YAML::Node doc;    // already parsed
for(YAML::Iterator it=doc.begin();it!=doc.end();++it) {
    std::string scalar;
    *it >> scalar;
    std::cout << "Found scalar: " << scalar << std::endl;
}

... or we can just loop through:

YAML::Node doc;    // already parsed
for(unsigned i=0;i<doc.size();i++) {
    std::string scalar;
    doc[i] >> scalar;
    std::cout << "Found scalar: " << scalar << std::endl;
}

And finally maps. For now, let's say our document is a map with all keys/values being scalars. Again, we can iterate:

YAML::Node doc;    // already parsed
for(YAML::Iterator it=doc.begin();it!=doc.end();++it) {
    std::string key, value;
    it.first() >> key;
    it.second() >> value;
    std::cout << "Key: " << key << ", value: " << value << std::endl;
}

Note that dereferencing a map iterator is undefined; instead, use the first and second methods to get the key and value nodes, respectively.

Alternatively, we can pick off the values one-by-one, if we know the keys:

YAML::Node doc;    // already parsed
std::string name;
doc["name"] >> name;
int age;
doc["age"] >> age;
std::cout << "Found entry with name '" << name << "' and age '" << age << "'\n";

One thing to be keep in mind: reading a map by key (as immediately above) requires looping through all entries until we find the right key, which is an O(n) operation. So if you're reading the entire map this way, it'll be O(n^2). For small n, this isn't a big deal, but I wouldn't recommend reading maps with a very large number of entries (>100, say) this way.

Optional Keys

If you try to access a key that doesn't exist, yaml-cpp throws an exception (see HowToParseADocument#When_Something_Goes_Wrong When Something Goes Wrong). If you have optional keys, you it's often easier to use FindValue instead of operator[]:

YAML::Node doc;    // already parsed
if(const YAML::Node *pName = doc.FindValue("name")) {
    std::string name;
    *pName >> name;
    std::cout << "Key 'name' exists, with value '" << name << "'\n";
} else {
    std::cout << "Key 'name' doesn't exist\n";
}

Getting More Complicated

The above three methods can be combined to read from an arbitrary document. But we can make life a lot easier. Suppose we're reading 3-vectors (i.e., vectors with three components), so we've got a structure looking like this:

struct Vec3 {
    float x, y, z;
};

We can read this in one operation by overloading the extraction (>>) operator:

void operator >> (const YAML::Node& node, Vec3& v)
{
    node[0] >> v.x;
    node[1] >> v.y;
    node[2] >> v.z;
}

// now it's a piece of cake to read it
YAML::Node doc;    // already parsed
Vec3 v;
doc >> v;
std::cout << "Here's the vector: (" << v.x << ", " << v.y << ", " << v.z << ")\n";

A Complete Example

Here's a complete example of how to parse a complex YAML file:

monsters.yaml

- name: Ogre
  position: [0, 5, 0]
  powers:
    - name: Club
      damage: 10
    - name: Fist
      damage: 8
- name: Dragon
  position: [1, 0, 10]
  powers:
    - name: Fire Breath
      damage: 25
    - name: Claws
      damage: 15
- name: Wizard
  position: [5, -3, 0]
  powers:
    - name: Acid Rain
      damage: 50
    - name: Staff
      damage: 3

main.cpp

#include "yaml-cpp/yaml.h"
#include <iostream>
#include <fstream>
#include <string>
#include <vector>

// our data types
struct Vec3 {
   float x, y, z;
};

struct Power {
   std::string name;
   int damage;
};

struct Monster {
   std::string name;
   Vec3 position;
   std::vector <Power> powers;
};

// now the extraction operators for these types
void operator >> (const YAML::Node& node, Vec3& v) {
   node[0] >> v.x;
   node[1] >> v.y;
   node[2] >> v.z;
}

void operator >> (const YAML::Node& node, Power& power) {
   node["name"] >> power.name;
   node["damage"] >> power.damage;
}

void operator >> (const YAML::Node& node, Monster& monster) {
   node["name"] >> monster.name;
   node["position"] >> monster.position;
   const YAML::Node& powers = node["powers"];
   for(unsigned i=0;i<powers.size();i++) {
      Power power;
      powers[i] >> power;
      monster.powers.push_back(power);
   }
}

int main()
{
   std::ifstream fin("monsters.yaml");
   YAML::Parser parser(fin);
   YAML::Node doc;
   parser.GetNextDocument(doc);
   for(unsigned i=0;i<doc.size();i++) {
      Monster monster;
      doc[i] >> monster;
      std::cout << monster.name << "\n";
   }

   return 0;
}

When Something Goes Wrong

... we throw an exception (all exceptions are derived from YAML::Exception). If there's a parsing exception (i.e., a malformed YAML document), we throw a YAML::ParserException:

try {
    std::ifstream fin("test.yaml");
    YAML::Parser parser(fin);
    YAML::Node doc;
    parser.GetNextDocument(doc);
    // do stuff
} catch(YAML::ParserException& e) {
    std::cout << e.what() << "\n";
}

If you make a programming error (say, trying to read a scalar from a sequence node, or grabbing a key that doesn't exist), we throw some kind of YAML::RepresentationException. To prevent this, you can check what kind of node something is:

    YAML::Node node;
    YAML::NodeType::value type = node.Type();  // should be:
                                               // YAML::NodeType::Null
                                               // YAML::NodeType::Scalar
                                               // YAML::NodeType::Sequence
                                               // YAML::NodeType::Map

Note about copying YAML::Node

Currently YAML::Node is non-copyable, so you need to do something like

    const YAML::Node& node = doc["whatever"];

This is intended behavior. If you want to copy a node, use the Clone function:

    std::auto_ptr<YAML::Node> pCopy = myOtherNode.Clone();

The intent is that if you'd like to keep a YAML::Node around for longer than the document will stay in scope, you can clone it and store it as long as you like.

Comment by steve.bu...@gmail.com, Apr 27, 2009

You reference test.yaml in the "HowToParseADocument" page. It would be nice for people new to yaml to have a copy of text.yaml either pasted on that page or a link to it so we can see the contents & how it's being parsed. It's easier to understand that way.

Thanks. Steve

Comment by lfzawa...@gmail.com, Jun 28, 2009

Yeah, maybe a large file with a lot o "Monsters" so we can have a look at the structure of the file being parsed. Anyway, great library!

Lucas

Comment by prog...@gmail.com, Jul 6, 2009

how can you parse map of maps:

a: { a: 5, b: 6, c: 7 }

Comment by project member jbe...@gmail.com, Jul 9, 2009

@prog112 Just parse one, then the other. E.g.,

node["a"]["b"] >> x;

should set x to 6

Comment by project member jbe...@gmail.com, Jul 10, 2009

@Steve and Lucas - good idea! I added a complete example.

Comment by prog...@gmail.com, Jul 10, 2009

Could you please also provide help with compiling source on windows? On linux everything was fine, but here...

CMake Error: CMake was unable to find a build program corresponding to "Visual S tudio 6". CMAKE_MAKE_PROGRAM is not set. You probably need to select a differe nt build tool. CMake Error: Could not find cmake module file:C:/Users/prog/CMakeFiles/CMakeCCom piler.cmake CMake Error: Could not find cmake module file:C:/Users/prog/CMakeFiles/CMakeCXXC ompiler.cmake

Do I really need M$ compiler? Can't use gcc? Sorry, I'm new to programming and not really familiar with CMake tool.

Comment by bobbyc...@gmail.com, Jul 11, 2009

Hi,

I have one question about the parser, is your parser able to parse any hexadecimal, date/timestamp, etc to the corresponding type of value. let say I have the following yaml: hexadecimal: 0x1234 Can it be read like: int hex; doc["hexadecimal"] >> hex;

Do you handle all the types defined here: http://yaml.org/type/index.html ?

thanks! I am developping on windows, until now using xml for data processing, I am trying yaml. I think it will be much faster than MSXML...

Comment by bobbyc...@gmail.com, Jul 11, 2009

Hi again,

I have another question, let's say I have optional nodes, that may OR NOT appear in my yaml file. What I don't really like, is that to do this I have to do a try/catch(RepresentationException??) because the value may not exist, for each value. what do you think?!

here is expl: int value1, value2; try {

node["param1"] >> value1;
} catch (YAML::RepresentationException?& e) {} try {
node["param2"] >> value2;
} catch (YAML::RepresentationException?& e) {}

thanks

Comment by bobbyc...@gmail.com, Jul 11, 2009

Hi again,

sorry for these lot of questions, but as you don't have any tags in svn, should we guess that what is in the trunk is something stable?

Comment by project member jbe...@gmail.com, Jul 11, 2009

@bobbycoul

Right now we only parse integers though std::stringstream, so it won't properly read 0x1234. This will be done eventually, I suppose. As for the other data types, the only implemented special case is for booleans.

For optional nodes, I just patched it to add Node::FindValue?, so you can do:

if(const Node *pValue = node.FindValue("param1")) {
   int value1;
   *pValue >> value1;
}

or something like that.

Finally, as for a stable branch, I haven't really thought about tagging one as such. The most recent version is almost always the most stable. (I personally always use the latest branch version in my other projects, but I suppose that's "dogfooding".)

Comment by bobbyc...@gmail.com, Jul 15, 2009

Hi,

Thanks for the reply. Now I have some things to tell/ask you:

-is it possible for you to maintain a VS2005 project/solution files, because I don't use VS2008, VS2005 cannot open the files, I recreated them anyway. I can give you the ones I created if you provide me your email address.

The following applies to revision 200. In your recent modifications I get the following errors:

>Cannot open source file: '.\src\alias.cpp': No such file or directory I have seen that you renamed the file to aliascontent.cpp/.h

>src\aliascontent.cpp(11) : warning C4138: '/' found outside of comment You should separate the and /.../

>src\node.cpp(22) : warning C4355: 'this' : used in base member initializer list according to msdn, seems dangerous to do this

>src\sequence.cpp(48) : warning C4267: 'return' : conversion from 'size_t' to 'unsigned int', possible loss of data I get many of these warnings, it's not error, but I appreciate having no warnings...

>src\stream.cpp(411) : warning C4996: 'std::basic_streambuf<Elem,Traits>::sgetn': Function call with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ 'Checked Iterators'

well, that's all ahah. Anyway this project is nice. continue like this!

I have seen you have added utf stuff, does it mean I can create a yaml file encoded in UTF8 with(out) bom?

regards.

Comment by project member jbe...@gmail.com, Jul 15, 2009

In general, I'd rather not have extra project/solution files. I'm already a little hesitant to have VS2008 project files, because you can autogenerate them from CMake (which is the point of having a CMake file).

Specifically:

1. The warning about */ outside a comment is maybe a silly warning, but I suppose I may fix that 2. As for using thisin an initialization list, it is (like all things) dangerous if used improperly, but I'm just storing the pointer, not doing anything with it. 3. The int/unsigned/size_t business is annoying, and I probably should use size_t everywhere, but it's no fun to type :) 4. Visual Studio complains a lot about unsafe function calls, and sometimes it's OK to use them :)

And as for the latest UTF stuff, you can do anything the YAML spec allows. So yes, if it's UTF8, you don't need a BOM.

Comment by bobbyc...@gmail.com, Jul 15, 2009

mmm thanks for the reply. I can read UTF8 encoded file, but as it's read in a "std::string", it doesn't really make sense, I think it should be converted to wstring?!

Also I would like to know if I can parse this kind of yaml file with your yaml-cpp code:

---
version: 1.0
date: 2009-07-15
list:
  - id: 1
    name: name1
    sublist:
      - name: list1name
        list: [word1, word2, word3]
  - id: 2
    name: name2
    sublist:
      - name: list2name
        list: [word4, word5, word6]

or are there limitations with your implementation right now?

regards & thanks.

Comment by project member jbe...@gmail.com, Jul 15, 2009

The latest commit actually implemented the conversion to wstring. So you can directly read a wstring from a YAML::Node.

And yes, the parser is (to my knowledge) complete.

Comment by bobbyc...@gmail.com, Jul 16, 2009

Hi, thanks for the fast reply!

about wstring, well you convert string to wstring so unicode strings are not correctly read from the yaml file, let's say you have this:

--- # yaml file
vers_ف_ion: 1.0 xx_ف_xx

you see what i mean? what could be nice to do to get it would be something like:

wstring str;
node[L"vers_ف_ion"] >> str;

with the cpp file encoded with unicode or utf8.

do you get my point? So in this case all could be in utf8, the keys, and also any text in the file. I don't want to bother you of course, but just to make yaml-cpp better! And as you are very active in your project, I take the opportunity. Anyway I think these kind of modifications are benefit for everybody, and I am not the first one to ask for utf8 support.

regards & thanks!

Comment by project member jbe...@gmail.com, Jul 16, 2009

Good point. I opened up an issue with this ( Issue 22 ) - I'm still new to different character sets, so I'm not sure how to fix this.

P.S. You can direct all further comments about this to the issue, and I'll respond there. If you have any other questions, you can either open up an issue (if it's a bug or something that needs clarification for others), or send me an email (my address is my user name @gmail.com)

Comment by jorn...@gmail.com, Jul 19, 2009

Hello, just wanted to contribute a recursive depth first function, for a yaml-cpp YAML::Node document:

void traverse(const YAML::Node & node, unsigned int depth = 0) {
    // recursive depth first
    YAML::CONTENT_TYPE type = node.GetType();
    string indent((size_t)depth, '\t');
    string out;
    switch (type)
    {
        case YAML::CT_SCALAR:
            node >> out;
            cout << indent << "SCALAR: " << out << endl;
            break;
        case YAML::CT_SEQUENCE:
            cout << indent << "SEQUENCE:" << endl;
            for (unsigned int i = 0; i < node.size(); i++) {
                const YAML::Node & subnode = node[i];
                cout << indent << "[" << i << "]:" << endl;
                traverse(subnode, depth + 1);
            }
            break;
        case YAML::CT_MAP:
            cout << indent << "MAP:" << endl;
            for (YAML::Iterator i = node.begin(); i != node.end(); ++i) {
                const YAML::Node & key   = i.first();
                const YAML::Node & value = i.second();
                key >> out;
                cout << indent << "KEY: " << out << endl;
                cout << indent << "VALUE:" << endl;
                traverse(value, depth + 1);
            }
            break;
        case YAML::CT_NONE:
            cout << indent << "(empty)" << endl;
            break;
        default:
            cerr << "Warning: traverse: unknown/unsupported node type" << endl;
    }
}
// traverse

Tested with g++ (GCC) 3.2.2.

Thanks, Jørn.

Comment by project member jbe...@gmail.com, Jul 19, 2009

Thanks , Jørn! However:

1. This doesn't appear to provide any extra functionality during the traversal (e.g., no callbacks) - it just dumps the node, and yaml-cpp already has that functionality (the emitter can emit Yaml::Nodes)

2. It doesn't provide any mechanism for quoting strings with nonprintable or newline characters.

3. It only handles maps with strings as keys (so it doesn't recurse to keys).

So I don't think I'll add anything like this (at least for the time being). Thanks for your interest!

Comment by bobbyc...@gmail.com, Jul 20, 2009

Hi,

I would like to tell you something about parsing time. In Release version, I can load my yaml file (about 250KB-300KB) in ~800ms. In Debug version, it's taking 30sec. Have you an idea if this could be improved?! I cannot share you the yaml file, but there is a big sequence, where each element contains a few sequences where one has many words as elements.

It's not a big big issue, but each time I am running debug mode, I have to be patient.

Thanks.

Comment by bobbyc...@gmail.com, Jul 20, 2009

I mean the following line is the one which takes this amount of time: parser.GetNextDocument(doc);

Comment by project member jbe...@gmail.com, Jul 20, 2009

@bobbycoul, you can compile yaml-cpp in Release mode and the rest of your program in Debug mode.

Comment by homechic...@gmail.com, Jul 23, 2009

When I try the simple example with YAML 1.2 code from the spec page, I get a doc size of 0. Examples on this page work fine. Does yaml-cpp support the entire YAML 1.2 spec, or just a subset. If so, is that subset documented?

Comment by project member jbe...@gmail.com, Jul 23, 2009

@homechicken, I just tried both examples you linked to (the invoice and the log file), and they both worked fine for me. What does your source look like?

Comment by homechic...@gmail.com, Jul 24, 2009
int main(int argc, char **argv) {
	try {
		std::ifstream fin("test.yaml");

		YAML::Parser parser(fin);
		YAML::Node doc;
		parser.GetNextDocument(doc);
		std::cout << "Doc node size is " << doc.size() << '\n';
	} catch(YAML::ParserException &e) {
		std::cout << "YAML Exception caught at line " << e.line + 1 << ", col " << e.column + 1 << ": " << e.msg << std::endl;
	}
	return 0;
}

I get a document size of 0 with the YAML 1.2 spec example, but a doc size of 3 (expected) with the Ogre/Dragon/Wizard example file above. I must be missing something here, but I don't see it. Thanks for the help, and the quick response!

Comment by project member jbe...@gmail.com, Jul 24, 2009

Ah, you mean doc.size()! If the YAML::Node is a sequence node, then that gives the number of elements in the sequence; otherwise (and in this case, it's a map node), it doesn't give any relevant info.

Comment by homechic...@gmail.com, Jul 24, 2009

Aha! It's starting to make sense to me now. Sorry about the confusion, I'm just getting started with YAML, having decided to use it instead of JSON in a hobby project of mine. Thanks again!

Comment by homechic...@gmail.com, Jul 25, 2009

Okay, new question. I have a map of "aliases" for a game:

n: north
s: south
d: down
"'": say
l: look

I talked to the people on the #yaml IRC channel, and they confirmed that "'" should be valid YAML, but yaml-cpp doesn't seem to accept it, I get an "end of map not found" error. Will yaml-cpp allow quoted indicators as scalars? (It parses properly in the ypaste page on yaml.org.)

Comment by project member jbe...@gmail.com, Jul 25, 2009

Now that is a bug!

I opened it up as  Issue 25 , and (I think) fixed it. Please test it on your end as well - I've been known to make mistakes :)

Also, if you have any comments on that issue in particular, please write them on the issue page.

Thanks for the catch!

Comment by homechic...@gmail.com, Jul 25, 2009

Thanks for the quick answer! I wasn't positive about that one being a bug (I am really new at YAML), so I thought I'd discuss it first. I'll be testing it shortly.

Comment by prog...@gmail.com, Jul 26, 2009

Hi

How can I parse this kind of document:

stats:

- something: value - sth2: value2

Tried node["stats"]["something"] but doesn't work :(

Comment by project member jbe...@gmail.com, Jul 26, 2009

That is a map of a sequence of maps. So you need to do

nodes["stats"][0]["something"]

Note: on these google wiki pages, enclose code in {{{ and }}} to get it to appear correctly.

Comment by prog...@gmail.com, Jul 28, 2009

Hi. I've written piece of code that was working really fine under the console. I moved it not changing anything to my game code. Unfortunately game does not start but gives an error (Runtime error, the application has requested runtime to terminate it in an unusual way). I debugged the code line by line and this error is made by this:

YAML::Parser parser(fin); 

So my question is - what can cause parser constructor to fail? Could this have anything to do with SDL? I seriously just copy-pasted it and put it in function. Maybe linking libraries order matter?

Comment by project member jbe...@gmail.com, Jul 28, 2009

Hmmm, that's a strange one. I don't know why it would do that. Try to move that line to a place after the game has already started, and also make sure that you recompile and relink everything. If you're feeling generous, compile yaml-cpp with no optimizations and try to debug into the constructor to see exactly where it's failing.

Comment by prog...@gmail.com, Jul 29, 2009

OMG! In this console project I added in linking fields SDL librarys, added #include "SDL.h" and changed int main() to int main(int argc, char argv) (SDL requires it) and IT DOES NOT WORK! Console window pops up but YAML parser doesn't do anything (checked with multiple examples). Do you know any reason what could it cause? Maybe you could check it with SDL?

Comment by project member jbe...@gmail.com, Jul 29, 2009

I don't know what the problem is. I use SDL for most of my games, and the yaml-cpp works fine with it. It is difficult to get SDL up and running, so I'm assuming your problem is with that. Try debugging step by step to see where the problem is.

Comment by homechic...@gmail.com, Aug 13, 2009

Just wanted to say thanks a lot for this library. I've got a fully-functioning YAML implementation in my MUD now thanks to yaml-cpp!

Comment by bobbyc...@gmail.com, Aug 22, 2009

Hi back from vacations

I wanted to reply you about your answer:

 Comment by jbeder,  Jul 20, 2009

@bobbycoul, you can compile yaml-cpp in Release mode and the rest of your program in Debug mode.

I tried this, and also check question in msdn forums, but the problem is with libc, if I have the static lib compiled in release, it will link to libcmt.lib, and my program (debug) will link to libcmtd.lib, so it cannot work, I tried many solutions (/force:multiple, ignore libcmt.lib, but doesn't work) do you have any idea?

Comment by project member jbe...@gmail.com, Aug 22, 2009

Bobby, you could try just enabling optimizations in the debug build

Comment by olav.ste...@gmail.com, Sep 19, 2009

Hi evryone! I tried installing your library on my Mac, and everything looked fine. But when I actually want to compile your "BAsic Parsing" example, I get the following error:

Undefined symbols:
  "YAML::Node::Node()", referenced from:
      _main in cc6YStvz.o
  "YAML::Parser::operator bool() const", referenced from:
      _main in cc6YStvz.o
  "YAML::Parser::GetNextDocument(YAML::Node&)", referenced from:
      _main in cc6YStvz.o
  "YAML::Node::~Node()", referenced from:
      _main in cc6YStvz.o
      _main in cc6YStvz.o
  "YAML::Parser::~Parser()", referenced from:
      _main in cc6YStvz.o
      _main in cc6YStvz.o
  "YAML::Parser::Parser(std::basic_istream<char, std::char_traits<char> >&)", referenced from:
      _main in cc6YStvz.o
ld: symbol(s) not found
collect2: ld returned 1 exit status

Maybe it's something trivial, I am no expert. Any ideas would be very much appreciated.

Comment by project member jbe...@gmail.com, Sep 19, 2009

Hi Olav,

Those are linker errors, which means you're not linking properly to the library. If you're compiling on the command line with gcc, you should add the option '-lyaml-cpp'. If you're using Xcode, I think you just have to drag the library (libyaml-cpp.so) into your project, but I'm not 100% sure.

Comment by olav.ste...@gmail.com, Sep 20, 2009

Great, that worked. Thanks!

Comment by shax...@gmail.com, Oct 13, 2009

Hello,

Is there a way to replicate representer/dumper functionality of pyyaml in yaml-cpp?

Comment by project member jbe...@gmail.com, Oct 13, 2009

Hi shaxbee,

C++ doesn't have reflection, so we can't do something as simple as in pyyaml (or in many of the YAML implementations in dynamic/duck typed languages). But you can mimic it by writing your own representer/dumper functions (see this document, and HowToEmitYAML).

Comment by tim.fi...@gmail.com, Nov 2, 2009

Re: I know this is an old reply, but...

All istreams will only figure out that a "0x" preface is hex if the decimal flag is cleared: unsetf( ios::dec ). Unintuitive, for sure, but that's C++. =D Decimal integers will be parsed correctly too, I recommend making the change to yaml's use of stringstreams internally.

Comment by project member jbe...@gmail.com, Nov 2, 2009

Tim, do you mean that you'd like

key: 0x1A

to be parsed as

int x;
node["key"] >> x; // x == 26

If so, I've been meaning to do this, but putting it off. I'll get to it eventually :)

Comment by tim.fi...@gmail.com, Nov 4, 2009

Yes, please. And all that's needed is to make a call to: stream.unsetf( ios::dec ) Thanks.

Comment by tim.fi...@gmail.com, Nov 4, 2009

Also, I'm having trouble with a visual studio complied version of yaml-cpp where the emitter is quoting the YAML::Key's to my maps. The mingw version of the very same code does not.

Comment by ctvo...@gmail.com, Nov 9, 2009

Hi, I also would love to be able to parse hex values. Tim's suggestion is good, and he is correct, C++ will try to infer the type of the value being read from the stream if you unset the format flags.

However I recommend doing the following: stream >> std::resetiosflags(std::ios::basefield) >> value;

An alternative suggestion, and one that would probably be more flexible in the future, is to have your Node operator >> use boost::lexical_cast.

Something like this maybe...

template <typename T>
inline void operator>>(const Node& node, T& value)
{
   std::string scalar;
   node.GetScalar(scalar);
   value = boost::lexical_cast<T>(scalar);
}

Lexical cast uses operator >> and << of the type T to do the conversion. Since the user defines these operators on their own T, you offload the actual conversion work to the user.

Comment by ctvo...@gmail.com, Nov 9, 2009

Also, after looking a bit at your regex code, I strongly suggest you consider using boost regular expressions. Why try to reinvent the wheel? :-)

http://www.boost.org/doc/libs/1_40_0/libs/regex/doc/html/index.html http://www.boost.org/doc/libs/1_40_0/libs/conversion/index.html

Comment by ctvo...@gmail.com, Nov 10, 2009

I was able to modify the code to use lexical_cast, and am now able to parse hex values. Here is the code I used.

// A useful little class so you can lexical_cast hexadecimal strings to actual hex values.  Implicitly may be converted to a size_t via the operator size_t().
class Hex
{
    public:
        operator size_t()
        {
            return data;
        }

        friend std::ostream & operator<<(std::ostream & os, Hex & hex)
        {
            return os << std::hex << hex.data;
        }

        friend std::istream & operator>>(std::istream & is, Hex & hex)
        {
            std::string tmp;
            is >> tmp;
            std::istringstream iss(tmp);
            iss.exceptions(std::ios_base::badbit | std::ios_base::failbit);
            iss >> std::hex >> hex.data;
            return is;
        }

    private:
        size_t data;
};

// Here are my modifications to include/conversion.h
#pragma once

#ifndef CONVERSION_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define CONVERSION_H_62B23520_7C8E_11DE_8A39_0800200C9A66


#include "null.h"
#include <string>
#include <sstream>

#include <boost/lexical_cast.hpp>

namespace YAML
{
    template <typename T>
	inline bool Convert(const std::string& input, T& output) {
        try
        {
            output = boost::lexical_cast<T>(input);
        }
        catch (boost::bad_lexical_cast const & e)
        {
            return false;
        }
		return true;
	}
	
    template <>
	bool Convert<bool>(const std::string& input, bool& output);
    
    template <>
	bool Convert<_Null>(const std::string& input, _Null& output);
}

#endif // CONVERSION_H_62B23520_7C8E_11DE_8A39_0800200C9A66

This is all of course, just food for thought! Whatever route you decide to go, please post it here, I would be interested in seeing how you solve the problem.

Thanks!

Carter

Comment by project member jbe...@gmail.com, Nov 10, 2009

Hi Carter,

Thanks for the suggestions. Please see  Issue 56  for more info on what we're doing with casting (and why a simple template Convert function won't work).

As for regex, I agree, it's silly to reinvent the wheel. However:

  1. Currently yaml-cpp has no dependencies, and it seems a shame to replace working code with a dependency, unless there's an extra benefit.
  2. We don't need the full power of regexes, just reeaaally simply ones. So it's possible that boost::regex would slow down the library. On the other hand, it might be (read: certainly is) better written than my regex code, so it might be faster.
  3. It'll be a pain to switch out the regex code...

Anyways, I've been meaning to try the switch just to see how it performs, but #1 is pretty important to me. If (and when) boost::regex becomes part of the standard C++ library, I'll jump on it in a heartbeat.

Comment by TheWag1...@gmail.com, Nov 16, 2009

I've been enjoying using yaml-cpp on a project I'm working on, but am stuck on parsing the following. Any suggestions would be a appreciated.

components: - !project,2008-03-06/component
    name: main 
- !project,2008-03-06/component
    name: Classes 
- !project,2008-03-06/component
    name: Client Interface 

Thanks, Ben

Comment by project member jbe...@gmail.com, Nov 16, 2009

Hi Ben,

That actually isn't valid YAML. First, you probably meant to add a newline between components: and the first - !project. Second, you can't have a comma in a tag shorthand. See the YAML spec section 6.9.1, specifically the subsection on "Tag Shorthands".

...the suffix must not contain the [, ], {, } and , characters...
Comment by project member jbe...@gmail.com, Nov 16, 2009

@Ben,

By the way, in the future, try to be more specific about your problem. You just wrote, "I am stuck on parsing the following." Are you getting an error message? Are you unsure of how to start parsing it?

Check out How To Ask Questions The Smart Way by Eric Raymond.

Comment by TheWag1...@gmail.com, Nov 16, 2009
components: 
- !project.foo.bar,2008-03-06/component 
  name: main
- !project.foo.bar,2008-03-06/component 
  name: Classes
- !project.foo.bar,2008-03-06/component 
  name: Client Interface
- !project.foo,bar,2008-03-06/component 
  name: Curses Interface

Sorry, code was mangled in the translation (4th time charm?). Lets hope this posts well. As for specifics, the error message is (from YAML::ParserException?):

yaml-cpp: error at line 6, column 3: end of sequence not found
Segmentation fault

I appreciate the link in the YAML specs. Hardest point of any new language is the spec...and the yaml specs are ... well, not reader friendly, imho.

Best, Ben

Comment by project member jbe...@gmail.com, Nov 16, 2009

@Ben,

It looks like the issue is the comma in your tags. You can either make them verbatim tags (use !<!whatever>) or use a TAG directive to save that prefix (!project.foo.bar,2008-03-06/).

Comment by ze.p.sma...@gmail.com, Dec 5, 2009

Hi guys.

So i have a YAML document that looks like this

-
  id: 1
  name: Mike
  date: 17-10-1979
  country: Finland
-
  id: 2
  name: Chris
  date: 25-4-1981
  country: Brasil
-
  id: 3
  name: Mike
  date: 13-5-1989
  country: Guatemala
-
  id: 4
  name: Josh
  date: 18-4-1967
  country: France

I use the following code to parse it:

for (unsigned int i =0; i< doc.size(); i++) {

		Jogador * jog = new Jogador();

		doc[i]>> (*jog);
		cout << jog->getNomeP() << endl;



	}

///and the overload function does this
void operator >> (const YAML::Node& node, Jogador & jog)
{
        YAML::Iterator it = node.begin();
	YAML::Iterator ite = node.end();
	string teste;
	string teste2;
	while (it!=ite){
		it.first() >> teste;
		it.second() >> teste2;
		cout << teste << ": " << teste2 <<   endl;
		++it;
	}
}

And this is what I get ond the console:

  date: 17-10-1979
  id: 1
  name: Mike  
  country: Finland

  date: 25-4-1981
  id: 2
  name: Chris
  country: Brasil

  date: 13-5-1989
  id: 3
  name: Mike
  country: Guatemala

  date: 18-4-1967
  id: 4
  name: Josh
  country: France

Why is this happening? Why is the date beeing parsed first? Am I doing something wrong?

Thanks

Comment by ze.p.sma...@gmail.com, Dec 5, 2009

Ups nevermind the cout after the doc[i] >> (*jog) its commented.

Comment by project member jbe...@gmail.com, Dec 5, 2009

In YAML, maps are unordered (so implementations can order them, or not, in any way they like). yaml-cpp alphabetizes by key (which is why I'm surprised that it doesn't parse country first - I tried your example file, and for me, it parses in the order country, date, id, name, as expected. Are you sure it's parsing date first?

In any case, if you want an ordered map, the standard way to do this is:

- id: 1
- name: Mike
- date: 17-10-1979
- country: Finland
Comment by ze.p.sma...@gmail.com, Dec 6, 2009

It doenst parse country first, because I translated the output (as I didn't knew the order was alphabetical), and in my language, date comes before country.

So, as a rule, if I have my maps like that, and I parse them with iterators, they will be sorted by key?

Thanks for the explanation, and sorry for misleading you.

Comment by project member jbe...@gmail.com, Dec 6, 2009

Yes, with the current yaml-cpp implementation, they are sorted by key. But this isn't required by the spec, and it may change in the future, so you shouldn't depend on it.

Comment by baeuml....@gmail.com, Dec 15, 2009

Is there a way to speed up parsing if I know the structure of the document beforehand (e.g. it will be a sequence of maps, and each of the maps has the same three keys) ?

Right now, a yaml file with 10000 sequence elements such as this:

- frame: 0
  timestamp: 0
  offset: 0
- frame: 1
  timestamp: 0.1
  offset: 100
- frame: 2
  timestamp: 0.2
  offset: 200
...

takes around 8 seconds to parse (quad-core 2.8ghz) which seems like a lot to me.

Thanks!

Comment by project member jbe...@gmail.com, Dec 15, 2009

@baeuml.kit,

No, unfortunately not. I'm planning to work on speeding the library up over the next month or two, when I get time, but there are two fundamental slow points during parsing:

1. The actual parsing (i.e., matching expressions), which I believe I can speed up

2. String copying, which I'm not so sure about. yaml-cpp will necessarily be slower than libyaml because libyaml produces events as it parses, and so it doesn't need to copy all of the strings (I believe - I haven't looked at the source in a while). yaml-cpp, on the other hand, "represents" the content after it parses, which currently copies everything over. That said, lazy copying will certainly speed things up here, and I plan to do that.

Comment by jonhtcph...@gmail.com, Dec 17, 2009

Hi there - I've recently downloaded yaml-cpp and started experimenting with it. (I'm planning on using it for data definition in a game I'm writing.) So far, it looks pretty promising! I did have a couple of observations though:

Firstly, I was wondering whether you're planning on adding something like a GetTag?() method on the YAML::Node class? This would be useful for validating the types of input data. For example, if I have a yaml document like this:

---
!Vector2 { x: 10., y: 20. }
...

Then I can do something like this in the input operator:

struct Vector2 { float x, y };

void operator>>(const YAML::Node &n, Vector2 &v) {
    assert(std::string("!Vector2") == n.GetTag()); //not the type we expected!
    n["x"] >> v.x;
    n["y"] >> v.y;
}

I did a quick experiment, adding an implementation for GetTag? in node.h like so:

const std::string &GetTag() const { return m_tag; }

which actually seems to work for my purposes. In "production code", throwing an exception would probably be a better course of action than an assertion, but the idea is that I'd be able to double-check that the tags in my YAML data match the types being instantiated at runtime. (I wouldn't consider myself anything more than a YAML novice, so if I'm completely wrong about how tags are supposed to work, please feel free to correct me!)

Secondly, I was wondering if you'd consider moving the headers in the include/ directory into a subdirectory (eg: include/yaml-cpp/ or similar)? This effectively puts the headers into their own "namespace" - it's a fairly common practice for C and C++ libraries, which reduces the chance of an include directive causing the wrong header to be included. This is just a little insurance in case I had a "null.h" or a "mark.h" in my application code (or another third-party library), for example, I could end up including the yaml-cpp headers unintentionally, whereas with this directive:

#include "yaml-cpp/node.h"

there's a lot less ambiguity over which header should be included.

Anyway, these are pretty minor issues, but I thought I'd mention them, in the interests of giving some feedback. I'll definitely be interested to see how yaml-cpp develops - YAML looks like a great language for data definition, and it's great to have an open-source implementation available in C++. Keep up the good work! :)

Comment by project member jbe...@gmail.com, Dec 17, 2009

@jonhtcphone,

There actually is a GetTag() method in the latest revision (if you check out with svn) - it's pretty close to pushing to a new version (there's just one more thing I want to do beforehand), and the new tag stuff is pretty solid. (There's actually quite a bit of difference between the last tagged version and the latest revision; tags were not parsed correctly, and now that's fixed. But the GetTag() method is essentially (possibly exactly, I don't recall) what you wrote.)

As for the include files, the make install command moves them into a include/yaml-cpp folder, so it effectively does work that way. I recommend using this, but I suppose perhaps it might be more consistent to keep them in a yaml-cpp subfolder in the source? What do you think?

Comment by jonhtcph...@gmail.com, Dec 17, 2009

Hi - it's nice to know that there's a GetTag?() coming to a public release soon - I'll be happy to wait for the next official release and I'll definitely give it a go. (And it's good to know that I wasn't completely misguided in how it would work too!)

I have to admit that I hadn't tried using the supplied makefiles, so I missed the install stage (my bad!). I generally prefer to include third-party libraries directly into my source tree, and build them from source along with my application code. (It's a slightly idiosyncratic way of working, but I find it tends to reduce the amount of pre-configuration required when trying to build my game from scratch on a fresh machine, or porting to a new OS, amongst other reasons.)

I can probably move the headers locally, but having said that, I prefer not to modify library code unless I absolutely have to, so if you did move the headers into include/yaml-cpp, it would make my life a tiny bit easier. And it would be a little more consistent, but I guess I'll leave it up to you ;)

Looking forward to the next release!

Comment by Joachim....@gmail.com, Feb 1, 2010

I would be interested to know which source files are used by the emitter, by the parser, or by both of them.

Actually, I would like to have the code base divided into subdirectories emitter, parser, common - and I would like a configuration option that allows me to produce just a parser library. Admittedly, this is pretty much a question of taste.

Comment by Michael....@gmail.com, Mar 11, 2010

I apologize if this is the wrong place to ask this. I went looking for an email address and couldn't find one. I'm seeing some behavior and I'm not sure if it's correct or not. I've looked through the yaml docs and I couldn't really determine for sure so I thought I'd ask here.

This is the code I'm using to extract the yaml values:

` YAML::Parser parser(fin);

YAML::Node doc; parser.GetNextDocument?(doc); for(YAML::Iterator it = doc.begin(); it != doc.end(); ++it) {
std::string key,value; it.first() >> key; it.second() >> value; mapkey? = value;
}`

when parsing this input it fails with the following error: yaml-cpp: error at line 5, column 10: illegal map value.

here's the file:

`invoice : 34843 date : 2001-01-23 billto : me shipto :you product : stuff tax : alot total : evenmore comments : yoyoyo`

however this input doesn't fail (I adapted it from http://www.yaml.org/start.html)

invoice: 34843 date : 2001-01-23 bill-to: &id001 ship-to: id001 tax : 251.42 total: 4443.52

My question to you is, is this expected behavior? Is the first one really invalid yaml? I don't know yaml deeply enough to know for sure. If it isn't I'd appreciate an explanation. If it is valid yaml I'm willing to hunt down the issue, I just want to make sure the mistake isn't on my end.

Ultimately if yaml is this brittle I'm probably going to go with something else for my configuration files. My needs are currently pretty simple and I'd prefer not requiring the users of my software to have to worry about the exact spacing of the configuration files.

Comment by Michael....@gmail.com, Mar 11, 2010

ormatting is bad so let me try that again.

fails:

invoice  : 34843
date     : 2001-01-23
billto   : me
shipto   :you
product  : stuff
tax      : alot
total    : evenmore
comments : yoyoyo

doesn't fail:

invoice: 34843
date   : 2001-01-23
bill-to: &id001
ship-to: *id001
tax  : 251.42
total: 4443.52

the code used to extract the values.

YAML::Parser parser(fin);
YAML::Node doc;
parser.GetNextDocument(doc);
for(YAML::Iterator it = doc.begin(); it != doc.end(); ++it)
{
        std::string key,value;
        it.first() >> key; it.second() >> value;
        map[key] = value;
}
Comment by project member jbe...@gmail.com, Mar 11, 2010

@Michael,

The problem is with your line

shipto   :you

YAML requires a space after the colon. This isn't as weird (or brittle) as you think - in most cases spaces (except for initial indents) doesn't matter. The question is, how can you tell if the colon is part of the word you or not? From the YAML spec:

Normally, YAML insists the “:” mapping value indicator be separated from the value by white space. A benefit of this restriction is that the “:” character can be used inside plain scalars, as long as it is not followed by white space. This allows for unquoted URLs and timestamps. It is also a potential source for confusion as “a:1” is a plain scalar and not a key: value pair.
Comment by Maestro....@gmail.com, Mar 12, 2010

Hi, guys. There's my question. All examples of yaml parsing in this tutorial(and parsing examples with source) are presented as direct-access to the field(struct, map, vector etc.). Like that -

node[0] >> v.x;

But what am I supposed to do if I work with object of some class with fields declared private, and getters and setters for access means? It's stupid to redo the whole project to use public fields just to be able of using deserialization. But what's the solution? Is there any? Of course I can do

SomeClass* obj = new SomeClass();
int someInt;
node[0] >> someInt;
obj->setSomeInt(someInt); 

But this is ugly as hell.

Comment by project member jbe...@gmail.com, Mar 12, 2010

@Maestro,

One thing you could do is make a member function

void SomeClass::Load(const YAML::Node& node);

where you do all of your deserializing, and then overload

void operator >> (const YAML::Node& node, SomeClass& obj) {
   obj.Load(node);
}
Comment by Maestro....@gmail.com, Mar 12, 2010

Oh, thanks. I'll try that.

Comment by emmabb2...@gmail.com, Mar 12, 2010

Hello all, and sorry for asking trivial questions, but I am new to YAML (and to C++ for that matter). I have a problem with hash merges that I have not been able to resolve. I've written a code to read a file like this one:

- channel: input
  units:  &input
     length: Angstrom
     energy: eV
     mass:   atomic_weight

- channel: output
  units: 
     length: Angstrom
     energy: eV
     mass:   atomic_weight

My code parses and reads this fine. However, if I try to use an anchor like so:

- channel: input
  units:  &input
     length: Angstrom
     energy: eV
     mass:   atomic_weight

- channel: output
  units: 
      <<:  *input

it fails after reading the first item in the channel list, with message: terminate called after throwing an instance of 'YAML::TypedKeyNotFound?<std::string>'

what(): yaml-cpp: error at line 10, column 7: key not found

It does look like yaml-cpp is not substituting the anchored information in the second item of the channel list.

Any hints? Thanks in advance.

Comment by Michael....@gmail.com, Mar 12, 2010

If the format is being produced by software then I could agree with you about it not being brittle.

bill-to :you vs bill-to: you

when it's being formatted by a human is another matter. I'm afraid I can't agree with that not being brittle.

I suppose I'll be using the tried and true ini file or rolling my own solution.

Thanks for the info jbeder, perhaps I'll find a use for yaml somewhere else.

Comment by project member jbe...@gmail.com, Mar 12, 2010

@emmabb,

Merging isn't implemented yet in yaml-cpp (see Issue 41). If you just write

- channel: output
  units: *input

It should work, but you won't be able to add any other key/value pairs like you would with a merge.

(By the way, the TypedKeyNotFound exception is thrown because you tried to access a node with a key that didn't exist. Presumably you wrote

unitsNode["length"] >> length;

so it actually parsed fine.)

Comment by emmabb2...@gmail.com, Mar 12, 2010

@jbeder,

Your suggestion did indeed work fine. I was not aware of the issue with merging not being yet implemented. Thanks a lot for your help!

Comment by kumarsa...@gmail.com, Mar 16, 2010

If I have a mapping {A: "a", B: a}, it parses "a" as a(double quotes are eaten up). I need the double quotes in the scalar. I could not locate any API to prevent this. Please help. Thanks in advance.

Comment by project member jbe...@gmail.com, Mar 16, 2010

@kumarsarth

That's YAML. If you want a string with double quotes, you'll have to escape them:

{A: "\"a\"", B: a}

By the way, in the future, please post questions on http://stackoverflow.com and tag them as yaml-cpp.

Comment by kumarsa...@gmail.com, Mar 17, 2010

@jbeder, Thanks for the answer.

Comment by vishnu...@gmail.com, May 25, 2010

I took the monster YAML example, and expanded on it further. It will parse the YAML into records, and then use those records to emit new YAML. You can find the code here.

#include "yaml.h"
#include <iostream>
#include <fstream>
#include <string>
#include <vector>


// our data models
struct Vec3
{
   float x, y, z;
};

struct Power
{
   std::string name;
   int damage;
};

struct Monster
{
   std::string name;
   Vec3 position;
   std::vector <Power> powers;
};

// operators for parsing
void operator >> (const YAML::Node& node, Vec3& v)
{
   node[0] >> v.x;
   node[1] >> v.y;
   node[2] >> v.z;
}

void operator >> (const YAML::Node& node, Power& power)
{
   node["name"] >> power.name;
   node["damage"] >> power.damage;
}

void operator >> (const YAML::Node& node, Monster& monster)
{
    node["name"] >> monster.name;
    node["position"] >> monster.position;
    const YAML::Node& powers = node["powers"];
    for(unsigned i = 0; i < powers.size(); i++)
    {
        Power power;
        powers[i] >> power;
        monster.powers.push_back(power);
    }
}

// operators for emitting
YAML::Emitter& operator << (YAML::Emitter& out, const Vec3& v)
{
    out << YAML::Flow;
    out << YAML::BeginSeq << v.x << v.y << v.z << YAML::EndSeq;
    return out;
}

YAML::Emitter& operator << (YAML::Emitter& out, const Power& power)
{
    out << YAML::BeginMap;
    out << YAML::Key << "name";
    out << YAML::Value << power.name;
    out << YAML::Key << "damage";
    out << YAML::Value << power.damage;
    out << YAML::EndMap;
    return out;
}

YAML::Emitter& operator << (YAML::Emitter& out, const Monster& monster)
{
    out << YAML::BeginMap;
    out << YAML::Key << "name";
    out << YAML::Value << monster.name;
    out << YAML::Key << "position";
    out << YAML::Value << monster.position;
    out << YAML::Key << "powers";
    out << YAML::Value;
    out << YAML::BeginSeq;
    for(size_t pidx = 0; pidx < monster.powers.size(); ++pidx)
    {
        out << monster.powers[pidx];
    }
    out << YAML::EndSeq;
    out << YAML::EndMap;
    return out;
}


int main()
{
   std::string monsters_yaml("- name: Ogre\n  position: [0, 5, 0]\n  powers:\n    - name: Club\n      damage: 10\n    - name: Fist\n      damage: 8\n- name: Dragon\n  position: [1, 0, 10]\n  powers:\n    - name: Fire Breath\n      damage: 25\n    - name: Claws\n      damage: 15\n- name: Wizard\n  position: [5, -3, 0]\n  powers:\n    - name: Acid Rain\n      damage: 50\n    - name: Staff\n      damage: 3\n");

    // list of monsters
    std::vector<Monster> monsters;

    // write out the monster.yaml 
    std::ofstream monsters_yaml_file;
    monsters_yaml_file.open("monsters.yaml");
    monsters_yaml_file << monsters_yaml;
    monsters_yaml_file.close();

    // read in the the monster.yaml 
    std::ifstream fin("monsters.yaml");
    YAML::Parser parser(fin);
    YAML::Node doc;
    parser.GetNextDocument(doc);
    for(size_t i = 0; i < doc.size(); i++)
    {
        Monster monster;
        doc[i] >> monster;
        monsters.push_back(monster);
        std::cout << monster.name << std::endl;
    }

    YAML::Emitter out;
    out << YAML::BeginSeq;
    for(size_t i = 0; i < monsters.size(); i++)
    {
        out << monsters[i];
    }
    out << YAML::EndSeq;

    std::cout << out.c_str() << std::endl;
    return 0;
}
Comment by iamphp...@gmail.com, Jul 14, 2010

Does yaml-cpp handle block order ?

I mean, if I write this :

B: 4 A: 2

Will I get B then A (and not A then B) ?

Comment by project member jbe...@gmail.com, Jul 14, 2010

@iamphpman,

In YAML, mapping keys are unordered. So there's no guarantee what you'll get. If you want to mimic an ordered map, do:

- B: 4
- A: 2

(This is just a sequence of single key/value pairs, but it is analogous to an ordered map.)

By the way, in the future, please post questions on http://stackoverflow.com and tag them as yaml-cpp.

Comment by iamphp...@gmail.com, Jul 14, 2010

Ok, thank you (and sorry for the bad post). =)

Comment by charlesw...@gmail.com, Jul 23, 2010

Hello,

I was wondering if there was a way to read YAML more than one YAML documents and extract the information from it. For example I have a YAML file called nod.yaml and included in this file is - Joint ID: 0

Joint Angle: 0
- Joint ID: 0
Joint Angle: -15
--- - Joint ID: 0
Joint Angle: 15
--- - Joint ID: 0
Joint Angle: -15
- Joint ID: 0
Joint Angle: 15
--- - Joint ID: 0
Joint Angle: -15
- Joint ID: 0
Joint Angle: 15
--- - Joint ID: 0
Joint Angle: -15
- Joint ID: 0
Joint Angle: 15
- Joint ID: 0
Joint Angle: -15
- Joint ID: 0
Joint Angle: 15
- Joint ID: 0
Joint Angle: 0

how do I read each document?

Comment by project member jbe...@gmail.com, Jul 23, 2010

@charles,

It's right at the top of the page, under "Basic Parsing":

YAML::Node doc;
while(parser.GetNextDocument(doc)) {
   // ...
}

By the way, in the future, please post questions on http://stackoverflow.com and tag them as yaml-cpp.

Comment by prog3...@gmail.com, Feb 22, 2011

When parsing yaml file, normally we get root node from parser.

And I'm wondering if I can reference the root node after parsing process. Like below.

    YAML::Node* globalRoot;
    
    void ParseDocument(filename)
    {
      YAML::Parser parser(fin)
      parser.GetNextDocument(*globalRoot);
    }
    
    void myFunction()
    {
      ParseDocument("myYAML.yml");

      // After the method above, we lose the parser instance since it's a local variable.
      // But if all child data is copied, below code should be safe.
      // If globalRoot is just pointing inside the parser, this could be dangerous.

      std::string stringKey;
      (*globalRoot)["myKey"] >> stringKey;
    }

Can I use like code above??

Comment by icepop...@gmail.com, Feb 25, 2011

I've little problem with getting to Vec3 content. Any help would be appreciated.

Comment by project member jbe...@gmail.com, Feb 25, 2011

@icepop, if you post a question with more details on stackoverflow.com and tag it yaml-cpp, I'll do my best to answer it!

Comment by christop...@gmail.com, Mar 1, 2011

Problem with exceptions.h, specifically the const initialization of the std::string literals. I believe the C++ standard states that only integer or enum constants can be initialized in the declaration.

Comment by TheReclu...@gmail.com, Mar 8, 2011

Is it possible to get an handle to the current position/context of the parser i.e. the line no. and the column ? I need to impose some extra restrictions in the yaml file syntax and print errors if the same are violated giving the line-no information.

Comment by project member jbe...@gmail.com, Mar 9, 2011

@TheReclu?:

1. I'm not sure what you mean, exactly - do you want to change the actual parsing algorithm? If so, that's not possible externally, but feel free to modify the code to your heart's content. Look in scanner.cpp and scantoken.cpp for details.

2. If you want to know where a particular node starts, call the GetMark?() function (it's just Mark() in the trunk).

3. Please post future questions on stackoverflow.com and tag them yaml-cpp :)

Thanks!

Comment by t.hiroya@gmail.com, Aug 12, 2011

Is reading from base64 not supported?

Comment by project member jbe...@gmail.com, Aug 23, 2011

@t.hiroya, no there isn't currently a built-in way to read base64 data. If you want to write one, I'd be happy to accept a patch :)

Comment by pashev.i...@gmail.com, Sep 7, 2011

Can I override operator>> for bool?

void operator>> (const YAML::Node & node, bool & b) {

// I'd like it to parse node as string "yes"/"no", "1"/"0"
}
Comment by F.Muell...@gmail.com, Nov 23, 2011

Hello,

is it possible to search for comments and parse them, too?


Sign in to add a comment
Powered by Google Project Hosting