diff --git a/libs/ymltree/src/YmlFormatter.cpp b/libs/ymltree/src/YmlFormatter.cpp index 2502109f0..e0f9d590a 100644 --- a/libs/ymltree/src/YmlFormatter.cpp +++ b/libs/ymltree/src/YmlFormatter.cpp @@ -25,8 +25,12 @@ static void EmitElement(YAML::Emitter& emitter, XMLTreeElement* element) auto& attributes = element->GetAttributes(); const string& text = element->GetText(); auto& children = element->GetChildren(); - if (!text.empty() && attributes.empty() && children.empty()) { - emitter << text; + if (attributes.empty() && children.empty()) { + if(!text.empty()) { + emitter << text; + } else { + emitter << YAML::Null; + } return; } @@ -40,9 +44,14 @@ static void EmitElement(YAML::Emitter& emitter, XMLTreeElement* element) } // treat everything else as a map emitter << YAML::BeginMap; - if (!attributes.empty()) { - for (auto [k, v] : attributes) { - emitter << YAML::Key << k << YAML::Value << v; + if(!attributes.empty()) { + for(auto [k, v] : attributes) { + emitter << YAML::Key << k; + if(!v.empty()) { + emitter << YAML::Value << v; + } else { + emitter << YAML::Null; + } } } @@ -70,6 +79,7 @@ std::string YmlFormatter::FormatElement(XMLTreeElement* rootElement, return RteUtils::EMPTY_STRING; } YAML::Emitter emitter; + emitter.SetNullFormat(YAML::EmptyNull); emitter << YAML::BeginMap; if (rootElement->GetChildCount() > 1 && rootElement->GetTag().empty()) { for (auto child : rootElement->GetChildren()) { diff --git a/libs/ymltree/src/YmlTreeParserInterface.cpp b/libs/ymltree/src/YmlTreeParserInterface.cpp index b57835eac..59c70488a 100644 --- a/libs/ymltree/src/YmlTreeParserInterface.cpp +++ b/libs/ymltree/src/YmlTreeParserInterface.cpp @@ -92,8 +92,9 @@ bool YmlTreeParserInterface::ParseMapNode(const YAML::Node& node) auto& key = it.first; auto& val = it.second; const string tag = key.as(); - if (val.IsScalar() && builder->HasRoot()) { - builder->AddAttribute(tag, val.as()); + if ((val.IsScalar() || val.IsNull()) && builder->HasRoot()) { + const string value = val.IsScalar() ? val.as() : ""; + builder->AddAttribute(tag, value); } else { if(!ParseNode(val, tag)) { return false; @@ -134,7 +135,6 @@ bool YmlTreeParserInterface::DoParseNode(const YAML::Node& node, const string& t return ParseMapNode(node); case NodeType::Null: - return false; case NodeType::Undefined: default: break; diff --git a/libs/ymltree/test/YmlTreeTest.cpp b/libs/ymltree/test/YmlTreeTest.cpp index f5a610c85..5b5e0e300 100644 --- a/libs/ymltree/test/YmlTreeTest.cpp +++ b/libs/ymltree/test/YmlTreeTest.cpp @@ -130,20 +130,42 @@ TEST(YmlTreeTest, KeyVal) { EXPECT_TRUE(tree.GetRoot()); root = tree.GetRoot() ? tree.GetRoot()->GetFirstChild() : nullptr; EXPECT_TRUE(root); + EXPECT_EQ(root->GetTag(), "key1"); + EXPECT_EQ(root->GetText(), "val1"); xmlContent = xmlFormatter.FormatElement(root); EXPECT_EQ(xmlContent, expected_output1); + string ymlContent1 = ymlFormatter.FormatElement(root); + EXPECT_EQ(ymlContent1, yaml_input1); + + const string yaml_input2 = "key2: "; // null node type (trailing space is intentional because added by emitter) + const string expected_output2 = XML_HEADER + "\n"; + + tree.Clear(); + EXPECT_TRUE(tree.ParseString(yaml_input2)); + EXPECT_TRUE(tree.GetRoot()); + root = tree.GetRoot() ? tree.GetRoot()->GetFirstChild() : nullptr; + EXPECT_TRUE(root); + EXPECT_EQ(root->GetTag(), "key2"); + EXPECT_EQ(root->GetText(), ""); + + xmlContent = xmlFormatter.FormatElement(root); + EXPECT_EQ(xmlContent, expected_output2); + string ymlContent2 = ymlFormatter.FormatElement(root); + EXPECT_EQ(ymlContent2, yaml_input2); + } TEST(YmlTreeTest, Map) { const string yaml_input = "map:\n\ + nul: \n\ one: 1\n\ two: 2"; - const string json_input = "map: {one: 1, two: 2}\n"; + const string json_input = "map: {nul:, one: 1, two: 2}\n"; - const string expected_output = XML_HEADER + "\n"; + const string expected_output = XML_HEADER + "\n"; YmlTree tree; EXPECT_TRUE(tree.ParseString(yaml_input)); @@ -175,6 +197,7 @@ TEST(YmlTreeTest, Nested) { one: 1\n\ two: 2\n\ three:\n\ + s_null: \n\ s_one: 3.1\n\ s_two: 3.2\n\ four:\n\ @@ -183,7 +206,7 @@ TEST(YmlTreeTest, Nested) { 4.2.b: b"; const string expected_output = XML_HEADER + "\n\ - \n\ + \n\ \n\ <->4.1\n\ <- 4.2.a=\"a\" 4.2.b=\"b\"/>\n\