【问题标题】:Build a Yaml document dynamically from c#从 c# 动态构建 Yaml 文档
【发布时间】:2016-05-09 13:10:10
【问题描述】:

是否可以使用 Yaml.DotNet 或其他库从 c# 动态构建 Yaml 文档?

我了解如何使用序列化来完成此操作,但这需要从对象结构开始。

我正在寻找一种方法来动态创建 Yaml 文档节点,就像使用 Xml 使用 XElement.Add(object) 方法一样。

【问题讨论】:

    标签: c# yaml yamldotnet


    【解决方案1】:

    您可以使用YamlDotNet 做到这一点。您首先创建一个YamlStream,向其中添加一个或多个document,然后您可以向其添加sequencesmappingsscalars

    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
                }
            )
        )
    );
    

    【讨论】:

    • 你能举个例子吗?我看不到任何在文档上添加内容的方法。
    • 我知道,这种语法很烂。欢迎拉取请求!
    • 感谢您的示例 - 我没想过将节点传递给构造函数。一个拉取请求现在在我的待办事项列表上。
    【解决方案2】:

    我现在已经弄清楚了如何使用 Yaml.Net 来做到这一点。 YamlStream 需要使用 Load() 方法加载一些初始内容。

    const string initialContent = "---\nversion: 1\n...";
    
    var sr = new StringReader(initialContent);
    var stream = new YamlStream();
    stream.Load(sr);
    

    然后您可以将 YamlDocument 的 RootNode 转换为具有 Add 方法的 YamlMappingNode。

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

    然后您可以在保存之前添加各种节点类型:

    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);
    

    这个例子的输出是:

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

    感谢 @Antoine Aubry 创建 Yaml.Net 并模糊地为我指明了正确的方向。

    【讨论】:

    • 如果您想从文本文件而不是字符串中读取初始内容,您可以使用此代码using(var reader = File.OpenText("<path-and-name-of-your-yaml-file")) { var stream = new YamlStream(); stream.Load(reader); }
    • 将YamlDocument的RootNode转换为YamlMappingNode时出现异常
    • @IMLERNCSHARP 它通常不会引发异常 - 请参阅 dotnetfiddle.net/D6K1D6。也许异常与文档内容中的某些内容有关 - 如果没有看到错误消息(和完整代码),我们无法真正判断。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-17
    相关资源
    最近更新 更多