PugiXML extracting data from recursive xml_tree_walker - c++

I'm trying to extract data from an XML that looks as shown in the image below using pugiXML traverse function. i'm able to print out all the data from the XML file using this function, however im not able to extract and store these into my variables. The main issue is that im not able to get node.name() and node.value() at the same time. node.name() comes in 1 iteration node.value() comes in the iteration after.
const char* node_types[] =
{
"null","Element", "Name", "InstancePath", "InstancePathDepth", "FieldAmount", "DataType", "TypeName", "DataSize", "ArrayTypeName", "LowerBound", "UpperBound", "BitPosition", "IsArray", "IsElementary", "IsProgram", "IsResource", "IsString", "IsStruct", "IsTask"
};
// tag::impl[]
struct simple_walker : pugi::xml_tree_walker
{
virtual bool for_each(pugi::xml_node& node)
{
for (int i = 0; i < depth(); ++i) std::cout << " "; // indentation
std::cout << node.name()<<" "<< node.value() << "\n";
return true; // continue traversal
}
};
The output is great, same as in the XML file.

You can skip elements that aren't of type node_element and use node.child_value() roughly like this:
virtual bool for_each(pugi::xml_node& node)
{
if (node.type() != pugi::node_element)
return true;
for (int i = 0; i < depth(); ++i) std::cout << " "; // indentation
std::cout << node.name()<<" "<< node.child_value() << "\n";
return true; // continue traversal
}
This is necessary because text (PCDATA) nodes are separate from element nodes: https://pugixml.org/docs/manual.html#node_pcdata

Related

CGAL: Output ID of facet associated to halfedge

This might be a very small issue, but I'm really wondering why it is not working. I'm trying to output the facet ID associated to every halfedge.
void MeshModel::printFacetsOfHalfedges() {
for (Polyhedron::Halfedge_iterator j = P_.halfedges_begin(); j != P_.halfedges_end(); ++j) {
int id = j->facet()->id();
std::cout << "Facet is: " << id << std::endl;
}
}
It starts with Facet is: 0 and then crashes. If I remove the line std::cout << "Facet is: " << id << std::endl; the iteration runs just fine. I'm really wondering how this simple int output messes up the code.
I'm aware that I could also iterate over facets (and this works fine), but I need the halfedge<->facet association.
I'm using CGAL::Polyhedron_items_with_id_3 and initialize my facet IDs at the beginning:
void MeshModel::initializeFacetIndices() {
std::size_t i = 0;
for (Polyhedron::Facet_iterator facet = P_.facets_begin(); facet != P_.facets_end(); ++facet) {
facet->id() = i++;
}
}
You need to check if the halfedge is not a boundary halfedge. In such a case j->facet() == Polyhedron::Face_handle()

Passing the elements of a vector to a different data structure by address

I am building a 2d game and I am storing all my enemy objects in an array. Right now I am trying to implement a quadtree. Currently I am just trying to build the quadtree and am not concerned with collisions. The code that pushes items to the quadtree is the following :
for (std::vector<Enemy>::iterator i=m_enemies.begin(); i != m_enemies.end(); ++i) {
std::cout << &(*i) << "Address of the object" << std::endl;
m_quad.Insert(&(*i));
}
The code for the Insert is the following :
void Quad::Insert(sf::RectangleShape* l_gameObject){
std::cout << &l_gameObject << "dsa1" << std::endl;
std::cout << "called insert " << m_objects.size() << std::endl;
m_objects.push_back(l_gameObject);
if (m_level < m_maxLevel) {
if (m_objects.size() > 3) {
std::cout<< "creating subregions " << m_objects.size() << std::endl;
m_subRegions.push_back(Quad(m_x,m_y,m_width/2.f, m_height/2, m_level + 1, m_maxLevel-1));
m_subRegions.push_back(Quad(m_x+m_width/2.f,m_y,m_width/2.f,m_height/2.f, m_level + 1, m_maxLevel-1));
m_subRegions.push_back(Quad(m_x+m_width/2.f, m_y + m_height/2.f, m_width/2.f, m_height/2.f, m_level + 1, m_maxLevel-1));
m_subRegions.push_back(Quad(m_x, m_y + m_height/2.f, m_width/2.f, m_height/2.f, m_level + 1, m_maxLevel-1));
std::vector<int> temp;
for (int i=0; i < m_objects.size(); i++){
for (int j=0; j< m_subRegions.size(); j++) {
if (m_subRegions[j].Contains(m_objects[i])) {
m_subRegions[j].Insert(m_objects[i]);
temp.push_back(i);
break;
}
}
}
for (int i = temp.size(); i > -1; i--){
m_objects.erase(m_objects.begin() + temp[i]);
}
}
}
}
When I print the address that I am passing to the Insert function and the one I have in the function I see that they are different. In fact the on in is always the same and the one I pass is always different as it should be. Could anyone clarify why that is the case ?
EDIT : Thanks to gsamaras for pointing out that I was printing the address of the parameter.
Followup question
When I use the methods of the object I am addressing in the first for loop I get the correct results, but when I do the same thing in the Insert function I get 0. Why is that ?
You are printing the address of the address.
Change this:
std::cout << &l_gameObject << "dsa1" << std::endl;
to this:
std::cout << l_gameObject << "dsa1" << std::endl;
in order to print the same thing as outside your of your function.
Inside Insert, you're printing the address of the parameter.
Outside Insert, you're printing the parameter's value.
You want
std::cout << l_gameObject << "dsa1" << std::endl;
since l_gameObject is the address you're passing in.

C++: Iterate Through Map

I'm trying to iterate through a map to read out a string and then all of the numbers in a vector to a file. I copied and pasted the typedef line, then adjusted it to my code, so I'm not positive it's correct. Anyways, Visual Studio is giving me errors on the use of iterator_variable in my loops. It says type name is not allowed. How can I fix this?
ofstream output("output.txt");
typedef map<string, vector<int>>::iterator iterator_variable;
for (iterator_variable iterator = misspelled_words.begin(); iterator != misspelled_words.end(); iterator++)
{
output << iterator_variable->first;
for (int i = 0; i < misspelled_words.size(); i++)
{
output << " " << iterator_variable->second[i];
}
output << endl;
}
You should access the iterator like iterator->first instead of iterator_variable->first.
And for the inner loop, you probably want to iterate through 0 to iterator->second.size() instead of misspelled_words.size().
ofstream output("output.txt");
typedef map<string, vector<int>>::iterator iterator_variable;
for (iterator_variable iterator = misspelled_words.begin(); iterator != misspelled_words.end(); iterator++)
{
output << iterator->first;
for (int i = 0; i < iterator->second.size(); i++)
{
output << " " << iterator->second[i];
}
output << endl;
}
You can use the the new range based for loop and auto for more concise and readable code too.
ofstream output("output.txt");
for ( auto const & ref: misspelled_words ) {
output << ref.first;
for (auto const & ref2 : ref.second ) {
output << " " << ref2;
}
output << "\n"; // endl force a stream flush and slow down things.
}

How to store the result in a Map in C++ and then iterate it and then prints out the result?

I have started working with C++ libcql library for Cassandra.. I am trying to retrieve data from Cassandra using C++ with libcql library..
Whenever I go on the command line using cqlsh and do select like this -
select record_name, record_value from profile_user where user_id = '1';
I always get the below output on the cql command line and in which record_name and record_value are actually a column of TEXT datatype which is UTF-8 encoded string.
record_name | record_value
-------------+--------------
e1 | hello
e2 | hello
Now Coming to C++ world-
Now I am trying to retrieve the same thing from the C++ libcql library... I will be running the same above select query in C++ and I want to return a map which will have e1, e2 as the key and HELLO as there value inside that map... It is possible to do it in C++?
/**
* This method will retrieve the data from Cassandra..
* And then call print_rows method to print it out on the console
*/
void get_attributes(string id){
try{
// some code
//Connection open
connection_open();
execute_query("USE testks;");
//this will give me the result back of the select query
cql_result_t& result = execute_query("select * from profile_user where key ='"+id+"';");
// and this is printing it out on the console
print_rows(result);
// some code
} catch (int e){
// some code here
}
}
Below is the method which will print out the results on the console after running my C++ program -
/**
* This method prints out the result on the console.. *
*
*/
void print_rows(cql::cql_result_t& result) {
while (result.next()) {
for (size_t i = 0; i < result.column_count(); ++i) {
cql::cql_byte_t* data = NULL;
cql::cql_int_t size = 0;
result.get_data(i, &data, size);
std::cout.write(reinterpret_cast<char*>(data), size);
std::cout << " | ";
}
std::cout << std::endl;
}
}
The result that I see on the console after running my above C++ program is something like this -
e1 | hello |
e2 | hello |
But what I am looking for is - Store the result in a Map in C++, in such a way such that key should be e1 and e2 in the Map.. And the value for them should be HELLO in the same Map... And then iterate the Map and print out the result in C++? Is this possible to do with the current code I have?
If yes, can anyone provide a simple example on this? Thanks...
It is basically a C++ question I guess.. Just retrieve the data and put it into the Map... But the problem I am facing is my background is totally in Java so having little bit hard time to figure out how to do that...
I have slightly changed my table design in this question to my original question here instead of using collection, now I am using composite keys..
But If I can figure out the solution to my previous question then I will be going with that approach, otherwise I will be going with this approach..
Thanks for the help...
Update Code:-
With the below change, it always print out first result twice? Not sure why?
void print_rows(cql::cql_result_t& result){
while (result.next()) {
for (size_t i = 0; i < result.column_count(); ++i) {
cql::cql_byte_t* data = NULL;
cql::cql_int_t size = 0;
result.get_data(i, &data, size);
// std::cout.write(reinterpret_cast<char*>(data), size);
// std::cout << " | ";
if(!flag) {
key = reinterpret_cast<char*>(data);
flag = true;
} else if(flag) {
value = reinterpret_cast<char*>(data);
m[key] = value;
flag = false;
}
}
std:map<std::string, std::string>::const_iterator it = m.begin();
for (;it!=m.end(); ++it ) {
std::cout << it->first << " : " << it->second << std::endl;
}
std::cout << std::endl;
}
}
e1 : hello
e1 : hello
e2 : hello
Is there anything wrong I am doing here?
So looks like your keys and values are alternating on each pass,
You can have something like this :
bool flag=false;
std::map<std::string, std::string> m;
std::string key,value;
void print_rows(cql::cql_result_t& result) {
while (result.next()) {
//...
if(!flag)
{
key=reinterpret_cast<char*>(data);
flag= true;
}
else if(flag)
{
value=reinterpret_cast<char*>(data);
m[key] = value;
flag = false;
}
// ....
}
//...
}
Now to transverse the map:
std::map<std::string, std::string>::const_iterator it=m.begin();
for(;it!=m.end();++it)
std::cout << it->first << " : " << it->second << std::endl;
Or if you're using C++11 :
for(const auto &it:m)
std::cout << it.first << " : "<< it.second << std::endl;

Expression Tree printLevel() function

I am implementing a tree which is a Binary Expression Tree. The leaf nodes are numbers, non-leaf nodes are math operators. Succesfully implemented printInorder,PostOrder, PreOrder, evaluate. But stucked with the printLevel().
Here is my int main ()
int main()
{
EXTree myTree;
string tests[] = {"2.1*3.1+4.2", "(2.0+1.3)/1.4", "2.*(1.3+1.4)","1.2*(1.3+1.4/0.5)","1.2*(1.3+1.4/0.5)-4.4", "1.2*(1.3+1.4/0.5)- (9/3)"};
for (int i=0; i < 6; i++)
{
myTree.build (tests[i]);
myTree.printInorder();
myTree.printPreorder();
myTree.printPostorder();
myTree.printLevel(); //Starting from level = 0
cout << "Evaulating myTree = " << format(myTree.evaluate(),2) << endl;
myTree.removeAll(); // removes all the nodes
}
}
printLevel(); only prints the level of the tree given above and its initally 0.
and here is my printLevel function.
void EXTree:: printLevel()
{
queue<Node*> levelq;
levelq.push(root);
cout << "Current Level is: ";
while( levelq.size() > 0 )
{
Node *cur = levelq.front();
cout << cur->Root << " ";
levelq.pop();
if (cur->Left) levelq.push(cur->Left);
if (cur->Right) levelq.push(cur->Right);
}
cout << endl;
}
But I really didnt understand how to implement the printLevel. Appreciate for any help to clarify it.
I just implemented the inOrder algorith to my printLevel and tried to change it but still didnt get it.
Since you have no problem with recursion, this would work without queue:
void EXTree:: printLevel()
{
int currentLevel = 0;
if (root)
{
cout << "Current Level is: ";
printLevelHelper(root,currentLevel);
}
else
cout << "This BST is Empty\n";
}
// Declare a private method:
void EXTree:: printLevelHelper(Node* &n, int &currentLevel)
{
cout << currentLevel << ' ';
if (n->Left)
{
currentLevel++;
printLevelHelper(n->Left,currentLevel);
currentLevel--;
}
if (n->Right)
{
currentLevel++;
printLevelHelper(n->Right,currentLevel);
currentLevel--;
}
}
When using Breadth First Search to print the nodes on one level immediately adjacent to each other, you'd just observe when the leftmost child of the leftmost node on the current level pops out of the queue: this must be the start of the next level. I could easily write the code but I'd guess it would incomprehensible for you and this homework is for you (I think you want to label your post appropriately as homework, BTW). Most of your implementation looks like a straight forward implementation. The only thing missing is detecting that the next level is reached.