How to replace a nodes pcdata or text using pugixml - c++

I am looking for an elegant solution to replacing a nodes pcdata using pugixml (version 1.6). For example, iterating through a node set and updating the child value to something.
pugi::xpath_node_set nodes = document.select_nodes("//a");
for (auto it = nodes.begin(); it != nodes.end(); it++)
{
std::cout << "before : " << it->node().child_value() << std::endl;
// SOME REPLACE GOES HERE
std::cout << "after : " << it->node().child_value() << std::endl;
}
I have used the:
it->node().append_child(pugi::node_pcdata).set_value("foo");
but as the name suggests it just appends the data but I can't find any functions along the lines of:
it->node().remove_child(pugi::node_pcdata);
Another note is that the attributes on the node are important and should remain unchanged.
Thanks for your help.

xml_text object is made for this purpose (among others):
std::cout << "before : " << it->node().child_value() << std::endl;
it->node().text().set("contents");
std::cout << "after : " << it->node().child_value() << std::endl;
Note that you can also use text() instead of child_value(), e.g.:
xml_text text = it->node().text();
std::cout << "before : " << text.get() << std::endl;
text.set("contents");
std::cout << "after : " << text.get() << std::endl;
This page has more details: http://pugixml.org/docs/manual.html#access.text

Related

Why are my map values being reset after i exit a loop

I have a map named monthly_volumes within an object's member function and every time it finishes making the assignments to the map's value fields, the values are reset to 0(the value i initialized the map with before)
for (auto i : monthly_volumes) {
i.second = get_monthly_volume(i.first, year);
cout << "Month check during loop" << i.first << ":" << i.second << endl;
}
for (auto i : monthly_volumes) {
//i.second = get_monthly_volume(i.first, year);
cout << "Month Check After loop" << i.first << ":" << i.second << endl;
}
This is the
Output of the code
You need to iterate through the map with a reference, like this:
for (auto &i : monthly_volumes)
// changes to i, changes monthly_volumes
Also, in c++17 you could use structured bindings to make the code easier to read:
for (auto &[k, v] : monthly_volumes) {
v = get_monthly_volume(k, year);
cout << "Month check during loop" << k << ":" << v << endl;
}
You need a reference to the map entries to change them. Your code is changing a copy of the map entry.
for (auto& i : monthly_volumes) {
i.second = get_monthly_volume(i.first, year);
cout << "Month check during loop" << i.first << ":" << i.second << endl;
}

How to print correctly const char* struct member of a list?

I am trying to display struct members of a list in OMNeT++, all members are displayed correctly unless the member which is of type const char*. I am confused because after three push_back in the list, when I display. All the members of the last pushed element is displayed correctly even the one of type const char*. But for the two first pushed elements, the member of type cont char* display nothing, garbage or "DETAIL (Ipv4)Drones.host[3].ipv4.ip".
Ipv4Address srcAddress = recMtlsd->getSrcAddress();
Ipv4Address dstAddress = recMtlsd->getDstAddress();
const char* position = recMtlsd->getPosition();
simtime_t time = recMtlsd->getTime();
int srcID = recMtlsd->getId();
EV_DEBUG << "Source : " << srcAddress << endl;
EV_DEBUG << "Destination : " << dstAddress << endl;
EV_DEBUG << "Position : " << position << endl;
EV_DEBUG << "Time : " << time << endl;
EV_DEBUG << "Source ID: " << srcID << endl;
// All precedent displays are working correctly
/*typedef struct Mtlsd{
Ipv4Address originatorAddr, destinationAddr;
const char *position;
int originatorId;
simtime_t time;
}MTLSD;*/
MTLSD recitem;
recitem.originatorAddr = srcAddress;
recitem.originatorId = srcID;
recitem.destinationAddr = dstAddress;
recitem.position = position;
recitem.time = time;
EV_DEBUG << "Source : " << recitem.originatorAddr << endl;
EV_DEBUG << "Destination : " << recitem.dstinationAddr << endl;
EV_DEBUG << "Position : " << recitem.position << endl;
EV_DEBUG << "Time : " << recitem.time << endl;
EV_DEBUG << "Source ID: " << recitem.srcID << endl;
// All precedent displays are working correctly
/*typedef struct Mtlsd_data{
list<MTLSD> q;
int ID;
}MTLSD_DATA;*/
list<MTLSD_DATA> mtlsd_file;
auto node = find_if(mtlsd_file.begin(), mtlsd_file.end(), [=] (MTLSD_DATA const& i){return (i.ID == srcID);});
bool found = (node != mtlsd_file.end());
if (!found)
{
MTLSD_DATA recdata;
recdata.ID = srcID;
recdata.q.push_back(recitem);
mtlsd_file.push_back(recdata);
EV_DEBUG << "For node " << srcID ;
for(auto claim=mtlsd_file.back().q.begin(); claim!=mtlsd_file.back().q.end();++claim)
{
EV_DEBUG << "(" << string(claim->position) << ", " << claim->time << ");" << endl;
}
// The precedent display works correctly
}
else
{
EV_DEBUG << "I already have data about the node " << node->ID << endl;
if (node->q.size() == 3)
{
EV_DEBUG << "I already have three time-location claim in the queue" << endl;
EV_DEBUG << "Here they are: ";
EV_DEBUG << "For node " << (*node).ID << endl;
for(auto fileclaim=(*node).q.begin(); fileclaim!=(*node).q.end();++fileclaim)
EV_DEBUG << "(" << string((*fileclaim).position) << ", " << (*fileclaim).time << ");" << endl;
EV_DEBUG << "I will delete the old one (" << node->q.front().position << ", " << node->q.front().time << ")" << endl;
node->q.pop_front();
}
node->q.push_back(recitem);
EV_DEBUG << "I have pushed this new one : (" << string(node->q.back().position) << ", " << node->q.back().time << ")" << endl;
}
EV_DEBUG << "Here they are all time-location claims in the queue : ";
for(auto fileclaims=node->q.begin(); fileclaims!=node->q.end();++fileclaims)
{
EV_DEBUG << "(" << string(fileclaims->position) << ", " << fileclaims->time << ");" << endl;
}
// The last element is displayed correctly, but those before not.
.
.
.

Replace an element in OMUMap(IBM Rational Rhapsody )

I want to overwrite an element corresponding to an key with new value.
What function I can use for this?
I tried by calling fun
myMap.add(key, value)
But this is not replacing the value already stored in map.
add() should work, here is an example:
OMUMap myMap;
char key1[] = "key-1";
char key2[] = "key-2";
/* initialize map */
myMap.add(static_cast<void*>(key1), static_cast<void*>("foo"));
myMap.add(static_cast<void*>(key2), static_cast<void*>("bar"));
std::cout << key1 << ": " << static_cast<char*>(myMap.getAt(key1)) << std::endl;
std::cout << key2 << ": " << static_cast<char*>(myMap.getAt(key2)) << std::endl;
/* replace 'key-1' value */
myMap.add(static_cast<void*>(key1), static_cast<void*>("bazzz"));
std::cout << key1 << ": " << static_cast<char*>(myMap.getAt(key1)) << std::endl;
std::cout << key2 << ": " << static_cast<char*>(myMap.getAt(key2)) << std::endl;
Output:
key-1: foo
key-2: bar
key-1: bazzz
key-2: bar

Get a mesh_3 'off' from Projection_traits_xy_3 constrained delaunay

I've computed a 2D constrained delaunay triangulation from 2.5D data using the projection_traits_xy_3 [1]. Now I would like to get a mesh that I can visualize.
I've managed to do that with 3d delaunay following the manual[2], how could I achieve it with a 2.5D CDT ?
[...]
typedef CGAL::Projection_traits_xy_3<K> Gt;
typedef CGAL::Constrained_Delaunay_triangulation_2<Gt, Tds> CDT;
[...]
CDT cdt;
cdt.insert(points.begin(),points.end());
[...]
¿?
[...]
std::ofstream out(outdir + "out.off");
Polyhedron output_mesh;
CGAL::output_surface_facets_to_polyhedron(¿?, output_mesh);
out << output_mesh;
[1] http://pastebin.com/HzAwrnW5
[2] http://doc.cgal.org/latest/Point_set_processing_3/index.html#chappoint_set_processing_3
http://doc.cgal.org/latest/Surface_reconstruction_points_3/
Here comes pseudocode forwriting it into an off file
cout << "OFF\n" << cdt.number_of_vertices()
<< " " << cdt.number_of_faces() << " 0" << std::endl;
std::map<vertex_handle,int> indices;
int counter = 0;
for all finite vertices v {
cout << v->point() <<std::endl;
indices.insert(v, counter++);
}
for all finite faces f {
cout << "3 " << indices[f->vertex(0)]
<< " " << indices[f->vertex(1)]
<< " " << indices[f->vertex(2)] << std::endl;
}
From #Andreas suggestion:
Here comes the code for writing it into an off file
std::ofstream outstream("output.off");
outstream << "OFF\n" << cdt.number_of_vertices()
<< " " << cdt.number_of_faces() << " 0" << std::endl;
std::map<CDT::Vertex_handle,int> indices;
int counter = 0;
for(CDT::Finite_vertices_iterator it = cdt.finite_vertices_begin(); it != cdt.finite_vertices_end(); ++it)
{
outstream << it->point() << std::endl;
indices.insert(std::pair<CDT::Vertex_handle,int>(it, counter++));
}
for(CDT::Finite_faces_iterator it = cdt.finite_faces_begin(); it != cdt.finite_faces_end(); ++it)
{
outstream << "3 " << indices[it->vertex(0)]
<< " " << indices[it->vertex(1)]
<< " " << indices[it->vertex(2)] << std::endl;
}

c++ std::cout unespected output

Hi I'm writing some debug output with std::cout with this code:
EDIT: as suggested I added a std::flush on each cout and an std::endl on each iteration
int
index = 0,
size = vector.size();
for (iterate trough a vector)
{
std::cout << "Actual element: " << index+1 << "/" << size << std::flush;
...
if (bad element)
{
std::cout << " -> Bad Element" << std::flush;
}
std::cout << std::endl;
}
The bad element string appear only after the successive element, why?
What am I missing?
Thanks a lot!
You should have a std::cout << std::flush (or std::cout << std::endl) in your for loop which is always done (even without bad elements), or at least after your for loop....