Results 1 to 10 of 10

Thread: QDomNode delete children

  1. #1
    Join Date
    Aug 2009
    Posts
    92
    Thanks
    5
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default QDomNode delete children

    I have a memory problem using QDomNode as the XML file is too big so I'm trying to create a row in a QDomDocument, write it to a file and delete it. I'm creating an Excel file so every row has a lot of cells. If I create e cell and then delete it, every thing is ok and the memory problem is solved but if I create a row, fill it with many cells, write all to a file and then delete the row, the row and all its cells are not deleted.

    I have debugged this line:

    Qt Code:
    1. oldRow.parentNode().removeChild(oldRow);
    To copy to clipboard, switch view to plain text mode 

    and I've seen that in the QDomNodePrivate* QDomNodePrivate::removeChild(QDomNodePrivate* oldChild) method, the child is actually removed from the list, but it's not deleted.
    How can delete it ?

    I've also tried oldRow.clear() but nothing happens.

  2. #2
    Join Date
    Jun 2006
    Posts
    81
    Thanks
    6
    Thanked 5 Times in 4 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QDomNode delete children

    From the QDomDocument doc:
    The parsed XML is represented internally by a tree of objects that can be accessed using the various QDom classes. All QDom classes only reference objects in the internal tree. The internal objects in the DOM tree will get deleted once the last QDom object referencing them and the QDomDocument itself are deleted.
    If your document is too large for DOM, go with SAX.

  3. #3
    Join Date
    Aug 2009
    Posts
    92
    Thanks
    5
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QDomNode delete children

    I know but I just need to apply a patch as switching to SAX would take too much time now.

  4. #4
    Join Date
    Jun 2006
    Posts
    81
    Thanks
    6
    Thanked 5 Times in 4 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QDomNode delete children

    I suppose "cells" are child nodes of "row" in your DOM? removeChild() is not recursive, you'd have to to this yourself, or else "cells" remain referenced.
    Last edited by zaphod.b; 9th December 2013 at 15:12. Reason: s/children of doc/referenced/

  5. #5
    Join Date
    Aug 2009
    Posts
    92
    Thanks
    5
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QDomNode delete children

    Good point thanks, but I tried this:

    Qt Code:
    1. if (node.isElement())
    2. {
    3. QDomElement e = node.toElement();
    4. QDomNodeList nodeList = e.childNodes();
    5. for( int i = 0; i < nodeList.count(); ++i )
    6. if( nodeList.at(i).isElement() )
    7. nodeList.at(i).parentNode().removeChild(nodeList.at(i));
    8. }
    9. node.parentNode().removeChild(node);
    To copy to clipboard, switch view to plain text mode 

    and it doesn't work.
    Node is the row and nodeList will contain all the "cells".
    I've debugged it and removeChild is actually called.

    If I delete each cell immediately after having created it (but it's something I cannot do), the used RAM goes up to 200MB, if I, instead, delete each row and all its children (the cells), the used RAM goes up to 900MB.

    Something is removed because if I don't call any removeChild method, the used RAM goes up to 1.8GB and the program crashes.

  6. #6
    Join Date
    Jun 2006
    Posts
    81
    Thanks
    6
    Thanked 5 Times in 4 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QDomNode delete children

    Are your rows and cells represented by element nodes only?
    If so, why do you still ask for isElement()?
    If not, why do you only remove the element nodes?
    What about attributes and text?

  7. #7
    Join Date
    Aug 2009
    Posts
    92
    Thanks
    5
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QDomNode delete children

    I've removed the isElement and added a clear() but it doesn't help.

    Qt Code:
    1. QDomNodeList nodeList = node.childNodes();
    2. for( int i = 0; i < nodeList.count(); ++i )
    3. {
    4. nodeList.at(i).clear();
    5. nodeList.at(i).parentNode().removeChild(nodeList.at(i));
    6. }
    7. node.clear();
    8. node.parentNode().removeChild(node);
    To copy to clipboard, switch view to plain text mode 

    clear() should remove all the attributes, no ?

    Anyway, we decided to switch to QXmlStreamWriter/QXmlStreamReader but it would be interesting to understand why this happens. I've also asked Qt/Digia customer support but still no answer.

  8. #8
    Join Date
    Jun 2006
    Posts
    81
    Thanks
    6
    Thanked 5 Times in 4 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QDomNode delete children

    clear() won't delete the node itself, just make null node of it.

    The code snippet you provided will now remove immediate child nodes, "cell elements" that is. I'd guess in general these cell elements will have child nodes themselves, e.g. text. As I wrote before, you'd have to make sure you traverse all descendant nodes, no matter what sublevel or type.

  9. #9
    Join Date
    Aug 2009
    Posts
    92
    Thanks
    5
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QDomNode delete children

    Quote Originally Posted by zaphod.b View Post
    clear() won't delete the node itself, just make null node of it.

    The code snippet you provided will now remove immediate child nodes, "cell elements" that is. I'd guess in general these cell elements will have child nodes themselves, e.g. text. As I wrote before, you'd have to make sure you traverse all descendant nodes, no matter what sublevel or type.
    It's exactly the other way round as explained by the Qt support via email, received today.

    When you call removeChild() then all it is going to do is remove it from the current tree, you still get a reference to the QDomNode that you have removed which is why it still exists in memory because it hasn't been actually deleted. If you want to ensure that the contents of the node are also deleted then you need to call clear() on that node. This will cause it to be deleted and point to a null node and therefore the memory should be freed up for you. See:

    http://qt-project.org/doc/qt-4.8/qdomnode.html#clear
    But I will answer them tomorrow because this is not true.
    If I only call clear(), nothing is deleted. The call to clear() seems to have no consequences.
    Or, probably, for clear() it's as you said about removeChild(), call it recursively.

  10. #10
    Join Date
    Jun 2006
    Posts
    81
    Thanks
    6
    Thanked 5 Times in 4 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QDomNode delete children

    Sorry for the confusion. I remembered incorrectly from the distant past.

    Meanwhile I had a look at the sources (5.1 but shouldn't have changed).
    As you'll have seen from your debugging, clear() simply calls the impl dtor[*]:
    Qt Code:
    1. void QDomNode::clear()
    2. {
    3. if (impl && !impl->ref.deref())
    4. delete impl;
    5. impl = 0;
    6. }
    To copy to clipboard, switch view to plain text mode 
    The dtor indeed iterates the children, thus traversing the tree[*]:
    Qt Code:
    1. QDomNodePrivate::~QDomNodePrivate()
    2. {
    3. QDomNodePrivate* p = first;
    4. QDomNodePrivate* n;
    5.  
    6. while (p) {
    7. n = p->next;
    8. if (!p->ref.deref())
    9. delete p;
    10. else
    11. p->setNoParent();
    12. p = n;
    13. }
    14. first = 0;
    15. last = 0;
    16. }
    To copy to clipboard, switch view to plain text mode 
    [*] I'm not sure what exactly deref() does, but if I interpret the asm correctly, it simply decrements the ref count and returns false if there are no references left, true otherwise. In the latter case deletion traversal terminates, and the node's subtree will dangle in the sense that it remains owned by the doc but is child of this node no more.

    My conclusion is, if not all of your "row" is deleted, there must be reference(s) to its descendant(s). This is in accordance with the doc cited in post #2.

    If you provided relevant parts of your code there might be a chance to locate the culprit.
    Last edited by zaphod.b; 11th December 2013 at 01:20.

Similar Threads

  1. convert from QDomElement to QDomNode
    By julida in forum Newbie
    Replies: 1
    Last Post: 18th January 2011, 04:18
  2. "new" + "delete" a QWidget and its children
    By vkincaid in forum Qt Programming
    Replies: 2
    Last Post: 19th January 2010, 22:51
  3. Replies: 3
    Last Post: 8th September 2008, 19:18
  4. QDomNode
    By sabeesh in forum Qt Programming
    Replies: 1
    Last Post: 14th September 2007, 07:11
  5. QDomNode
    By sabeesh in forum Qt Programming
    Replies: 1
    Last Post: 6th September 2007, 13:18

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.