06-11-2020 07:19 AM
Hi,
I am using the Ydk-gen's XmlSubtreeCodec Api's.
I am able to generate Ydk-gen C++ Object from Xml data using decode API.
Now I want to convert Ydk-gen C++ Object to Xml string using encode(). Somehow I am unable to do that, as from the documentation provided I am unable to understand the "path::RootSchemaNode" parameter being passed to the API.
std::string XmlSubtreeCodec::encode(Entity & entity, path::RootSchemaNode & root_schema)
Please help me in understanding and using this API. Thanks in Advance!
P.S. I have tried passing the object reference directly but it fails(probably due to some mistake).
Solved! Go to Solution.
06-17-2020 03:59 PM - edited 06-17-2020 08:49 PM
Hi Ankit
Here is an example of how XmlSubrtreeCodec could be used without connecting to device. You need though generate your model package in order to use Model API.
#include <iostream>
#include <spdlog/spdlog.h>
#include "ydk/codec_provider.hpp"
#include "ydk/xml_subtree_codec.hpp"
#include "ydk_openconfig/openconfig_bgp.hpp"
#include "ydk_openconfig/openconfig_bgp_types.hpp"
using namespace ydk;
using namespace openconfig;
using namespace std;
void config_bgp(openconfig_bgp::Bgp & bgp)
{
bgp.global->config->as = 65172;
bgp.global->config->router_id = "1.2.3.4";
auto neighbor = make_shared<openconfig_bgp::Bgp::Neighbors::Neighbor>();
neighbor->neighbor_address = "6.7.8.9";
neighbor->config->neighbor_address = "6.7.8.9";
neighbor->config->peer_as = 65001;
neighbor->config->local_as = 65001;
neighbor->config->peer_group = "IBGP";
bgp.neighbors->neighbor.append(neighbor);
}
void aug_cap_func() {
// do nothing
}
int main(int argc, char* argv[])
{
auto logger = spdlog::stdout_color_mt("ydk");
logger->set_level(spdlog::level::debug);
CodecServiceProvider cp{EncodingFormat::XML};
cp.initialize("my_openconfig", "/Users/ygorelik/ydk-gen/yang/openconfig-nis", aug_cap_func);
auto & root = cp.get_root_schema_for_bundle("my_openconfig");
try {
auto bgp = openconfig_bgp::Bgp{};
config_bgp(bgp);
XmlSubtreeCodec xml_codec{};
auto xml_bgp_config = xml_codec.encode(bgp, root);
cout << xml_bgp_config << endl;
}
catch(YError & e) {
cerr << "Error details: " << e << endl;
return 1;
}
return 0;
}
The program produces the following output:
<bgp xmlns="http://openconfig.net/yang/bgp">
<global>
<config>
<as>65172</as>
<router-id>1.2.3.4</router-id>
</config>
</global>
<neighbors>
<neighbor>
<neighbor-address>6.7.8.9</neighbor-address>
<config>
<peer-group>IBGP</peer-group>
<neighbor-address>6.7.8.9</neighbor-address>
<peer-as>65001</peer-as>
<local-as>65001</local-as>
</config>
</neighbor>
</neighbors>
</bgp>
For your information I have attached CMakeLists.txt file.
There is also another, probably more effective, way of initializing schema and getting root schema node:
auto repo = path::Repository{"/Users/ygorelik/ydk-gen/yang/openconfig-nis"};
std::vector<path::Capability> empty_caps;
auto root = repo.create_root_schema(empty_caps); // here root is shared_ptr<RootSchemaNode>
...
XmlSubtreeCodec xml_codec{};
auto xml_bgp_config = xml_codec.encode(bgp, *root);
I suggest to try the last method first and explore, if it is working for you.
06-11-2020 10:21 AM
Hello Ankit
Here is documentation explaining what the RootSchemaNode is. In short it is a root of all YANG model nodes that you are working on. It is built internally when you create service provider, and there is API to get it and provide to the codec. For example you have instantiated NetconfServiceProvider. Then:
provider = NetconfServiceProvider(address, port, username, password)
root_schema_node = provider.get_session().get_root_schema()
If you are not connecting to a device, then you need to use CodecServiceProvider and initialize it on some repository (directory) of YANG models. In the example below the bundle package is used to define the repository:
from ydk.models import cisco_ios_xe as xe
from ydk.models.cisco_ios_xe import Cisco_IOS_XE_native as xe_native
from ydk.providers import CodecServiceProvider
from ydk.entity_utils import XmlSubtreeCodec
provider = CodecServiceProvider(type="xml")
provider.initialize('cisco_ios_xe', xe.__path__[0] + '/_yang')
root_schema = provider.get_root_schema('cisco_ios_xe')
xml_codec = XmlSubtreeCodec()
# create YDK native model object for IOS XE model generation
native = xe_native.Native()
# build object native ...
# Encode object as XML string
xml_output = xml_codec.encode(native, root_schema)
print(xml_output)
# ...
# Decode XML string to YDK object (need provide top level entity of expected object)
native_entity = xml_codec.decode(xml_output, xe_native.Native())
06-11-2020 11:22 AM
06-11-2020 02:42 PM
I think something wrong with pointers. Could you attach your program to the post. I will then try to reproduce the issue.
06-11-2020 09:58 PM
06-17-2020 03:59 PM - edited 06-17-2020 08:49 PM
Hi Ankit
Here is an example of how XmlSubrtreeCodec could be used without connecting to device. You need though generate your model package in order to use Model API.
#include <iostream>
#include <spdlog/spdlog.h>
#include "ydk/codec_provider.hpp"
#include "ydk/xml_subtree_codec.hpp"
#include "ydk_openconfig/openconfig_bgp.hpp"
#include "ydk_openconfig/openconfig_bgp_types.hpp"
using namespace ydk;
using namespace openconfig;
using namespace std;
void config_bgp(openconfig_bgp::Bgp & bgp)
{
bgp.global->config->as = 65172;
bgp.global->config->router_id = "1.2.3.4";
auto neighbor = make_shared<openconfig_bgp::Bgp::Neighbors::Neighbor>();
neighbor->neighbor_address = "6.7.8.9";
neighbor->config->neighbor_address = "6.7.8.9";
neighbor->config->peer_as = 65001;
neighbor->config->local_as = 65001;
neighbor->config->peer_group = "IBGP";
bgp.neighbors->neighbor.append(neighbor);
}
void aug_cap_func() {
// do nothing
}
int main(int argc, char* argv[])
{
auto logger = spdlog::stdout_color_mt("ydk");
logger->set_level(spdlog::level::debug);
CodecServiceProvider cp{EncodingFormat::XML};
cp.initialize("my_openconfig", "/Users/ygorelik/ydk-gen/yang/openconfig-nis", aug_cap_func);
auto & root = cp.get_root_schema_for_bundle("my_openconfig");
try {
auto bgp = openconfig_bgp::Bgp{};
config_bgp(bgp);
XmlSubtreeCodec xml_codec{};
auto xml_bgp_config = xml_codec.encode(bgp, root);
cout << xml_bgp_config << endl;
}
catch(YError & e) {
cerr << "Error details: " << e << endl;
return 1;
}
return 0;
}
The program produces the following output:
<bgp xmlns="http://openconfig.net/yang/bgp">
<global>
<config>
<as>65172</as>
<router-id>1.2.3.4</router-id>
</config>
</global>
<neighbors>
<neighbor>
<neighbor-address>6.7.8.9</neighbor-address>
<config>
<peer-group>IBGP</peer-group>
<neighbor-address>6.7.8.9</neighbor-address>
<peer-as>65001</peer-as>
<local-as>65001</local-as>
</config>
</neighbor>
</neighbors>
</bgp>
For your information I have attached CMakeLists.txt file.
There is also another, probably more effective, way of initializing schema and getting root schema node:
auto repo = path::Repository{"/Users/ygorelik/ydk-gen/yang/openconfig-nis"};
std::vector<path::Capability> empty_caps;
auto root = repo.create_root_schema(empty_caps); // here root is shared_ptr<RootSchemaNode>
...
XmlSubtreeCodec xml_codec{};
auto xml_bgp_config = xml_codec.encode(bgp, *root);
I suggest to try the last method first and explore, if it is working for you.
06-17-2020 09:14 PM
Discover and save your favorite ideas. Come back to expert answers, step-by-step guides, recent topics, and more.
New here? Get started with these tips. How to use Community New member guide