Abstract base class of YAML data nodes.
See YamlScalar, YamlSequence and YamlMapping for actual data classes.
See http://yaml.org/ for the official definition of Information Models of YAML.
YAML data structure is defined as follows. Note that this does not represents the text syntax of YAML text but does logical data structure.
yaml-stream ::= yaml-document*
yaml-document ::= yaml-directive* yaml-node
yaml-directive ::= YAML-directive | TAG-directive | user-defined-directive
yaml-node ::= yaml-scalar | yaml-sequence | yaml-mapping
yaml-scalar ::= yaml-tag yaml-value
yaml-sequence ::= yaml-tag yaml-node*
yaml-mapping ::= yaml-tag ( yaml-node yaml-node )*
yaml-tag ::= yaml-global-tag yaml-local-tag
yaml-global-tag ::= "tag:" taggingEntity ":" specific [ "#" fragment ]
yaml-local-tag ::= "!" yaml-local-tag-name
Namely,
A YAML stream consists of zero or more YAML documents.
A YAML documents have zero or more YAML directives and a root YAML node.
A YAML directive is either YAML-directive, TAG-directive or user-defined-directive.
A YAML node is either YAML scalar, YAML sequence or YAML mapping.
A YAML scalar consists of a YAML tag and a scalar value.
A YAML sequence consists of a YAML tag and zero or more child YAML nodes.
A YAML mapping cosists of a YAML tag and zero or more key/value pairs of YAML nodes.
A YAML tag is either a YAML global tag or a YAML local tag.
A YAML global tag starts with "tag:" and described in the "tag:" URI scheme defined in RFC4151.
A YAML local tag starts with "!" with a YAML local tag name
// Construct YAML node tree YamlNode node = new YamlSequence( // !!seq node new YamlScalar("abc"), // !!str node new YamlScalar("!!int", "123"), // !!int node new YamlScalar("!!float", "1.23"), // !!float node new YamlSequence( // nesting !!seq node new YamlScalar("def"), new YamlScalar("ghi") ), new YamlMapping( // !!map node new YamlScalar("key1"), new YamlScalar("value1"), new YamlScalar("key2"), new YamlScalar("value2"), new YamlScalar("key3"), new YamlMapping( // nesting !!map node new YamlScalar("value3key1"), new YamlScalar("value3value1") ), new YamlScalar("key4"), new YamlScalar("value4") ) ); // Convert it to YAML stream string yaml = node.ToYaml(); // %YAML 1.2 // --- // - abc // - 123 // - 1.23 // - - def // - ghi // - key1: value1 // key2: value2 // key3: // value3key1: value3value1 // key4: value4 // ... // Load the YAML node from the YAML stream. // Note that a YAML stream can contain several YAML documents each of which // contains a root YAML node. YamlNode[] nodes = YamlNode.FromYaml(yaml); // The only one node in the stream is the one we have presented above. Assert.AreEqual(1, nodes.Length); YamlNode resotred = nodes[0]; // Check if they are equal to each other. Assert.AreEquel(node, restored); // Extract sub nodes. var seq = (YamlSequence)restored; var map = (YamlMapping)seq[4]; var map2 = (YamlMapping)map[new YamlScalar("key3")]; // Modify the restored node tree map2[new YamlScalar("value3key1")] = new YamlScalar("value3value1 modified"); // Now they are not equal to each other. Assert.AreNotEquel(node, restored);
YamlNode is an abstract class that represents a YAML node.
In reality, a YamlNode is either YamlScalar, YamlSequence or YamlMapping.
All YamlNode has YamlNode.Tag property that denotes the actual data type represented in the YAML node.
Default Tag value for YamlScalar, YamlSequence or YamlMapping are "tag:yaml.org,2002:str"
, "tag:yaml.org,2002:seq"
, "tag:yaml.org,2002:map"
.
Global tags that starts with "tag:yaml.org,2002:"
( = "!!"
, like "!!str"
, "!!seq"
and "!!map"
. Tags in the formal style and the shorthand form can be converted to each other by the static methods of YamlNode.ExpandTag and YamlNode.ShorthandTag(string). In addition to these three basic tags, this library uses "!!null"
, "!!bool"
, "!!int"
, "!!float"
and "!!timestamp"
tags, by default.
YamlNodes can be read from a YAML stream with YamlNode.FromYaml(string), YamlNode.FromYaml(Stream), YamlNode.FromYaml(TextReader) and YamlNode.FromYamlFile(string) static methods. Since a YAML stream generally consist of multiple YAML documents, each of which has a root YAML node, these methods return an array of YamlNode that is contained in the stream.
YamlNodes can be written to a YAML stream with YamlNode.ToYaml(), YamlNode.ToYaml(Stream), YamlNode.ToYaml(TextWriter) and YamlNode.ToYamlFile(string).
The way of serialization can be configured in some aspects. The custom settings are specified by an instance of YamlConfig class. The serialization methods introduced above has overloaded styles that accepts YamlConfig instance to customize serialization. It is also possible to change the default serialization method by modifying
A YamlScalar has YamlScalar.Value property, which holds the string expression of the node value.
A YamlSequence implements
YamlMapping implements
Implicit cast operators from string, bool, int, double and DateTime to YamlNode is defined. Thus, anytime YamlNode is required in C# source, naked scalar value can be written. Namely, methods of YamlSequence and YamlMapping accept such C# native types as arguments in addition to YamlNode types.
var map = new YamlMapping(); map["Time"] = DateTime.Now; // implicitly converted to YamlScalar Assert.IsTrue(map.ContainsKey(new YamlScalar("Time"))); Assert.IsTrue(map.ContainsKey("Time")); // implicitly converted to YamlScalar
Equality of YamlNodes are evaluated on the content base. Different YamlNode objects that have the same content are evaluated to be equal. Use Equals(object) method for equality evaluation.
In detail, two YamlNodes are logically equal to each other when the YamlNode and its child nodes have the same contents (YamlNode.Tag and YamlScalar.Value) and their node graph topology is exactly same.
YamlNode a1 = "a"; // implicit conversion YamlNode a2 = "a"; // implicit conversion YamlNode a3 = new YamlNode("!char", "a"); YamlNode b = "b"; // implicit conversion Assert.IsTrue(a1 != a2); // different objects Assert.IsTrue(a1.Equals(a2)); // different objects having same content Assert.IsFalse(a1.Equals(a3)); // Tag is different Assert.IsFalse(a1.Equals(b)); // Value is different var s1 = new YamlMapping(a1, new YamlSequence(a1, a2)); var s2 = new YamlMapping(a1, new YamlSequence(a2, a1)); var s3 = new YamlMapping(a2, new YamlSequence(a1, a2)); Assert.IsFalse(s1.Equals(s2)); // node graph topology is different Assert.IsFalse(s1.Equals(s3)); // node graph topology is different Assert.IsTrue(s2.Equals(s3)); // different objects having same content and node graph topology