I try to create an xml_node from another scope, but I don't know if it's possible, is there another way to create a node to be added later without going through the parent ?
void makeDocument(const pugi::xml_node& nodeD)
{
std::shared_ptr<pugi::xml_document> document = std::shared_ptr<pugi::xml_document>(new pugi::xml_document);
pugi::xml_node infos = document->prepend_child(pugi::node_declaration);
infos.append_attribute("version") = "1.0";
infos.append_attribute("encoding") = "UTF-8";
infos.append_attribute("standalone") = "yes";
pugi::xml_node root = document->append_child("Document");
pugi::xml_node nodeA = root.append_child("A");
pugi::xml_node nodeC = root.append_child("C");
pugi::xml_node nodeB = root.insert_child_before("B",nodeC);
//INSERT MY nodeD HERE ?
...
document->save_file("test.xml");
}
int main()
{
pugi::xml_node nodeD; //CREATE A NEW NODE WITHOUT PARENT ?
makeDocument(nodeD);
return 0;
}
the only two questions that come close to my problem are this one and this one, thank's for your help !
Related
I want to delete all root nodes of the root scene of a Qt3DWindow. It contains multiple hierarchy levels of nodes. I want to remove the references and delete the objects. What is the simplest way to do that?
I used this recursive function to do it:
void deleteChildrenRecursively(Qt3DCore::QNodeVector& vector)
{
foreach(Qt3DCore::QNode* node, vector){
Qt3DCore::QEntity* entity = (Qt3DCore::QEntity*)node;
QList<Qt3DCore::QComponent*> componentsToDelete;
foreach(Qt3DCore::QComponent* component, entity->components()){
entity->removeComponent(component);
delete(component);
component = NULL;
}
deleteChildrenRecursively(node->childNodes());
delete(node);
node = NULL;
}
}
It deletes all QEntity and its QComponent objects recursively.
Usage:
Qt3DCore::QEntity* rootEntity = new Qt3DCore::QEntity();
view->setRootEntity(rootEntity)
...
deleteChildrenRecursively(rootEntity->childNodes());
The #Codev 's answer is reasonable but it crashed on my application with Qt Version 5.12.2.
So I rewrite the recursive method and it works.
void delete_entity_recursively(Qt3DCore::QNode *node){
Qt3DCore::QEntity* entity = dynamic_cast<Qt3DCore::QEntity*>(node);
if(entity == nullptr){
return;
}
auto components_to_delete = entity->components();
foreach(auto *component,components_to_delete){
entity->removeComponent(component);
delete(component);
component = nullptr;
}
auto children_nodes = entity->childNodes();
foreach(auto *child_node, children_nodes){
delete_entity(child_node);
}
delete entity;
entity = nullptr;
}
usage:
Qt3DCore::QEntity* entity = new Qt3DCore::QEntity();
...
delete_entity_recursively(entity);
The value in some variables are being overlapped.
When I loop the first time on a node everything works fine but when I loop again, the values from the last variable created are printed and sometimes the program stops working.
#include "pugixml.hpp"
#include "pugixml.cpp"
pugi::xml_node varnodes = getNodesXML(varsFilepath);
for (pugi::xml_node node = varnodes.first_child(); node; node = node.next_sibling()){
printf("%s: %s\n", node.name(), node.attribute("id").value());
}
pugi::xml_node blocknodes = getNodesXML(blocksFile);
for (pugi::xml_node node = blocknodes.first_child(); node; node = node.next_sibling()){
printf("%s: %s\n", node.name(), node.attribute("id").value());
//varnodes.append_copy(node);
}
pugi::xml_node funcnodes = getNodesXML(functionsFile);
for (pugi::xml_node node = funcnodes.first_child(); node; node = node.next_sibling()){
printf("%s: %s\n", node.name(), node.attribute("id").value());
//varnodes.append_copy(node);
}
//looping on varnodes after other nodes have been created (the program crash and this is not displayed)
for (pugi::xml_node node = varnodes.first_child(); node; node = node.next_sibling())
printf("%s: %s\n", node.name(), node.attribute("id").value());
for (pugi::xml_node node = blocknodes.first_child(); node; node = node.next_sibling())
printf("%s: %s\n", node.name(), node.attribute("id").value());
for (pugi::xml_node node = funcnodes.first_child(); node; node = node.next_sibling())
printf("%s: %s\n", node.name(), node.attribute("id").value());
This is how I get the nodes from different files:
pugi::xml_node getNodesXML(char *filepath){
printf("%s\n",filepath);
pugi::xml_document doc;
pugi::xml_parse_result result = doc.load_file(filepath);
if(!result) printf("Error reading file: %s\n%s\n", filepath, result.description());
pugi::xml_node nodes = doc.child("nodes");
if(!nodes) printf("Error finding root <nodes> in: \n%s\n", filepath);
return nodes;
}
The xml is something like this:
varnodes.xml <nodes><node id="firstvar"></node></nodes>
blocknodes.xml <nodes><node id="firstblock"></node></nodes>
funcnodes.xml <nodes><node id="firstfunc"></node></nodes>
//Expected output:
node: firstvar
node: firstblock
node: firstfunc
node: firstvar
node: firstblock
node: firstfunc
//Wrong output Im getting (sometimes the program just stops working):
node: firstvar
node: firstblock
node: firstfunc
node: firstfunc
node: firstfunc
node: firstfunc
Error:
Unhandled exception at 0x00eb0cdd in practice.exe: 0xC0000005: Access violation reading location 0xfeeeff0a.
main.exe has stopped working and points me to this function:
PUGI__FN xml_attribute xml_node::attribute(const char_t* name_) const
{
if (!_root) return xml_attribute();
> for (xml_attribute_struct* i = _root->first_attribute; i; i = i->next_attribute)
if (i->name && impl::strequal(name_, i->name))
return xml_attribute(i);
return xml_attribute();
}
When I add the code from the function to main.cpp the variables values print perfectly (I think there is something wrong in the way I return a value from getNodesXML() )
I think I solved it:
In the function I create an object of type pugi::xml_document which is local, if I create the doc object as a pointer everything works correctly but I guess I'll have a memory leak so probably I need another function that returns that object to delete later or create a global variable to store it.
This is a documented feature request on the pugi Github:
https://github.com/zeux/pugixml/issues/104
To return an object from a function, an appropriate copy constructor for the object must be defined - it may be either an lvalue or xvalue copy constructor. the pugi::xml_document, and other pugi objects, do not have such a copy constructor, and your intuition about wrapping it in a pointer is the correct way to handle this.
However, as you've noticed, a raw pointer will give you a handful of problems to contend with, not least of which is a potential memory leak in your client code. If you are using C++1x, you can get around all of these problems by returning a smart pointer, for example a unique_ptr:
#include <memory>
std::unique_ptr< pugi::xml_node> getNodesXml( char* filepath) {
// Implementation
return std::make_unique( myXmlNode);
}
And in your client code:
auto varNodes = getNodesXml(varsFilepath);
for (auto node = varNodes->first_child(); node; node =
node.next_sibling()){
printf("%s: %s\n", node.name(), node.attribute("id").value());
//varnodes.append_copy(node);
}
I have tried to find an answer but couldn't find a clear explenation.
i have the following code:
slist* mergeLists(slist *List1,slist *List2)
{
slist *temp=*List1;
while (temp->next!=NULL)
temp=temp->next;
temp->next=List2;
return List1;
}
I Try to merge List1 with List2 and return List 1 (List 1->List 2).
but i have no idea how o continue.
Thank you
A search in my bookmarks yields this link, which previously helped me achive the merging of two lists. What this basically does is
Node *nodeC; // The combined list
while(nodeA != null && nodeB != null)
{
if(nodeA->Id <= nodeB->Id) // Sorting
{
nodeC->Link = nodeA; // Set nodeA to the link of the current node
nodeC = nodeA; // Set nodeC to nodeA (which is now the current node)
nodeA = nodeA->link;
}
else
{
nodeC->Link = nodeB;
noceC = nodeB;
nodeB = nodeB->Link;
}
}
I have few xml files, and some of it's nodes contains "reference" to each other. I want to add content of this xml as child to nodes, that contains this references
void GameObject::ExpandNode(QDomElement& expNode)
{
if ((expNode.tagName() == "Instance" && expNode.attribute("type") == "library") ||
(expNode.tagName() == "library" && expNode.hasAttribute("file")))
{
QString fileName;
if (expNode.tagName() == "Instance" )
fileName = FindLib(expNode.attribute("definition")).attribute("file");
else
fileName = expNode.attribute("file");
QFile nestedFile(fileName);
QDomDocument nestedLib;
nestedLib.setContent(&nestedFile);
QDomElement nestedNode = libDoc->createElement("NestedLibrary");
nestedNode.setAttribute("path", fileName);
nestedNode.appendChild(nestedLib);
expNode.appendChild(nestedNode);
}
QDomNode childNode = expNode.firstChild();
while (!childNode.isNull())
{
if (childNode.isElement())
ExpandNode(childNode.toElement());
childNode = childNode.nextSibling();
}
}
But what i got is
no matching function for call to 'GameObject::ExpandNode(QDomElement)' ExpandNode(childNode.toElement());
How can i do this right?
^
It was wrong decision - to call ExpandNode, using temporary object. Solution is
QDomNode childNode = expNode.firstChild();
while (!childNode.isNull())
{
if (childNode.isElement())
{
QDomElement childElem = childNode.toElement();
ExpandNode(childElem);
}
childNode = childNode.nextSibling();
}
isElement : If this function returns true, it does not imply that this object is a QDomElement;
do this
QDomElement node = childNode.toElement;
if (node != NULL)
{
ExpandNode(node);
}
This is an interview question that I found interesting.
Write a method that takes a pointer to a Node structure as a parameter and returns a complete copy of the passed-in data structure.
The Node structure contains two pointers to other Node structures.
For example, the method signature could look like so:
Node* Copy(Node* root);
Note - Do not make any assumptions about the data structure – it could be a tree, linked list, graph, etc.
How can this be done for any data structure ?
In the generic graph case, you need a mapping from nodes in the original graph to nodes in the new graph, so that when a cycle is encountered, the proper link gets created. If you happen to have extra temporary space in each node, large enough to hold a pointer, then you can store the mapping directly in the nodes; otherwise, you'll need to use an external map, such as an associative array or hash table.
Then it's just a matter of traversing the graph, copying nodes, and looking up the corresponding edges. Something like this:
struct Node
{
Node(int _data) : data(_data) { memset(links, 0, sizeof(links)); }
int data;
Node *links[2];
}
Node *Copy(Node *root)
{
typedef std::map<Node*, Node*> NodeMap;
NodeMap nodeMap;
std::deque<Node*> nodesToVisit;
// Set up initial new root and mapping for the root
Node *newRoot = new Node(root->data);
nodeMap[root] = newRoot;
// Breadth-first search the graph
nodesToVisit.push_back(root);
while(!nodesToVisit.empty())
{
Node *cur = nodesToVisit.front();
nodesToVisit.pop_front();
Node *newCur = nodeMap[cur];
for(int i = 0; i < 2; i++)
{
Node *link = cur->links[i];
if(link)
{
// If we've already created the corresponding node for this
// link, use that. Otherwise, create it and add it to the map.
NodeMap::iterator mappedLink = nodeMap.find(link);
if(mappedLink != nodeMap.end())
{
newCur->links[i] = mappedLink->second;
}
else
{
Node *newLink = new Node(link->data);
nodeMap[link] = newLink;
newCur->links[i] = newLink;
nodesToVisit.push_back(link);
}
}
}
}
return newRoot;
}
The problem as stated is impossible. You have to assume that the entire data structure is stored entirely within the content of nodes that are accessible from that initial one. But that is not an assumption you are allowed to make. Even your standard basic double linked list might not fit that description.
class Copier {
std::map <Node*, Node*> copies;
Node* Copy(Node* n) {
if (!n) return 0;
Node*& copy = copies[n];
if (!copy) {
copy = new Node();
copy.node1 = Copy(n.node1);
copy.node2 = Copy(n.node2);
}
return copy;
}
}
Node* Copy(Node* root) {
if (root == NULL)
return root;
std::unordered_map<Node*, Node*> completed;
std::deque<Node*> todo;
Node *ret = new Node(*scur);
completed.push_back(std::make_pair(root, ret));
todo.push_pack(root);
//while there's more nodes to duplicate
do {
//duplicate the node
Node* oldNode = todo.back();
Node* newNode = completed[cur];
todo.pop_back();
if(oldNode->left) {
auto iter = completed.find(oldNode->left);
//if it has a left child that needs duplicating, add it to the todo list
if (iter == completed.end()) {
newNode->left = new Node(*(oldNode->left));
completed.push_back(std::make_pair(oldNode->left, newNode->left));
todo.push_back(oldNode->left);
} else {
newNode->left = completed[oldNode->left];
}
}
if(oldNode->right) {
auto iter = completed.find(oldNode->right);
//if it has a right child that needs duplicating, add it to the todo list
if (iter == completed.end()) {
newNode->right = new Node(*(oldNode->right));
completed.push_back(std::make_pair(oldNode->right, newNode->right));
todo.push_back(oldNode->right);
} else {
newNode->right= completed[oldNode->right];
}
}
} while(todo.empty() == false)
//return the translation of the root
return ret;
}
Doesn't have stack overflow, root can be NULL, doesn't fail if left or right are NULL.
[Edit]Adam Rosenfield made me realize this was incorrect if there was loops in the network. Had to rewrite almost from scratch. Due to the large amount of code required, I prefer his code's for loop.
return new Node(*node);
Trick question?
You should write it recursively;
Node * Copy( Node * root )
{
Node * node_copy;
node_copy = new Node; // Assume Node1 and Node2 are initialized to 0
node_copy->content = root->content;
if( root->Node1 ) node_copy->Node1 = Copy( root->Node1 );
if( root->Node2 ) node_copy->Node2 = Copy( root->Node2 );
return node_copy;
}
So, this does not make any assumption on the data type
Given that a copy constructor exists that copies only the contents of a node and not its children:
Node* Copy(Node* root)
{
Node* copy = new Node(*root);
copy->left = Copy(root->left);
copy->right = Copy(root->right);
return copy;
}
In a more general sense, I would use copy-constructors that fully copy the entire data structure:
Node* Copy(Node* root)
{
return new Node(*root);
}