Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Build a Yaml document dynamically from c#

Is it possible to build a Yaml document dynamically from c# with Yaml.DotNet or another library?

I understand how this can be done using serialisation, however that requires starting with an object structure.

I'm looking to find a way to create the Yaml document nodes on the fly as you would with Xml using the XElement.Add(object) method for example.

like image 696
sparkplug Avatar asked May 09 '16 13:05

sparkplug


2 Answers

You can do that using YamlDotNet. You start by creating a YamlStream, add one or more document to it, then you can add sequences, mappings and scalars to it.

Here is an example on how to do it:

var address = new YamlMappingNode(
    new YamlScalarNode("street"),
    new YamlScalarNode("123 Tornado Alley\nSuite 16") { Style = YamlDotNet.Core.ScalarStyle.Literal },
    new YamlScalarNode("city"),
    new YamlScalarNode("East Westville"),
    new YamlScalarNode("state"),
    new YamlScalarNode("KS")
) { Anchor = "main-address" };

var stream = new YamlStream(
    new YamlDocument(
        new YamlMappingNode(
            new YamlScalarNode("repeipt"),
            new YamlScalarNode("Oz-Ware Purchase Invoice"),
            new YamlScalarNode("date"),
            new YamlScalarNode("2007-08-06"),
            new YamlScalarNode("customer"),
            new YamlMappingNode(
                new YamlScalarNode("given"),
                new YamlScalarNode("Dorothy"),
                new YamlScalarNode("family"),
                new YamlScalarNode("Gale")
            ),
            new YamlScalarNode("items"),
            new YamlSequenceNode(
                new YamlMappingNode(
                    new YamlScalarNode("part_no"),
                    new YamlScalarNode("A4786"),
                    new YamlScalarNode("descrip"),
                    new YamlScalarNode("Water Bucket (Filled)"),
                    new YamlScalarNode("price"),
                    new YamlScalarNode("1.47"),
                    new YamlScalarNode("quantity"),
                    new YamlScalarNode("4")
                ),
                new YamlMappingNode(
                    new YamlScalarNode("part_no"),
                    new YamlScalarNode("E1628"),
                    new YamlScalarNode("descrip"),
                    new YamlScalarNode("High Heeled \"Ruby\" Slippers"),
                    new YamlScalarNode("price"),
                    new YamlScalarNode("100.27"),
                    new YamlScalarNode("quantity"),
                    new YamlScalarNode("1")
                )
            ),
            new YamlScalarNode("bill-to"), address,
            new YamlScalarNode("ship-to"), address,
            new YamlScalarNode("specialDelivery"),
            new YamlScalarNode("Follow the Yellow Brick\n" +
                               "Road to the Emerald City.\n" +
                               "Pay no attention to the\n" +
                               "man behind the curtain.")
            {
                Style = YamlDotNet.Core.ScalarStyle.Literal
            }
        )
    )
);
like image 112
Antoine Aubry Avatar answered Oct 18 '22 00:10

Antoine Aubry


I've now worked out how to do this using Yaml.Net. The YamlStream needs to be loaded with some initial content using the Load() method.

const string initialContent = "---\nversion: 1\n...";

var sr = new StringReader(initialContent);
var stream = new YamlStream();
stream.Load(sr);

You can then cast the RootNode of the YamlDocument to YamlMappingNode which has an Add method.

var rootMappingNode = (YamlMappingNode)stream.Documents[0].RootNode;   
rootMappingNode.Add("shout", "yay!");

You can then add a variety of node types before saving:

var props = new YamlMappingNode();
props.Add("prop1", "value1");
props.Add("prop2", "value2");
rootMappingNode.Add("itemWithProps", props);

var props2 = new YamlMappingNode();
props2.Add("prop1", "value1");
props2.Add("prop2", "value2");

var props3 = new YamlMappingNode();
props3.Add("prop1", "value1");
props3.Add("prop2", "value2");

var seq = new YamlSequenceNode();
seq.Add(props2);
seq.Add(props3);
rootMappingNode.Add("sequenceOfItems", seq);

var col = new YamlSequenceNode();
col.Style = SequenceStyle.Flow;
col.Add("a");
col.Add("b");
col.Add("c");

var seqMapping = new YamlMappingNode();
seqMapping.Add("collection", col);
seq.Add(seqMapping);

using (TextWriter writer = File.CreateText("C:\\temp\\test.yaml"))
    stream.Save(writer, false);

The output from this example is:

version: 1
shout: yay!
itemWithProps:
  prop1: value1
  prop2: value2
sequenceOfItems:
- prop1: value1
  prop2: value2
- prop1: value1
  prop2: value2
- collection: [a, b, c]
...

Thanks to @Antoine Aubry for creating Yaml.Net and vaguely pointing me in right direction.

like image 20
sparkplug Avatar answered Oct 18 '22 00:10

sparkplug