QDomDocument won't insert QDomElement - c++

I'm doing something with XML and now I'm confused.
This code works perfectly:
QDomElement new_item = doc.createElement(name);
new_item.setAttribute("type", value.typeName());
new_item.setAttribute("value", value.toString());
doc.elementsByTagName(section).at(0).appendChild(new_item);
But if I would create QDomElement myself (without calling createElement method), then it doesn't get inserted into the document. Something like this doesn't work:
QDomElement new_item;
new_item.setTagName(name);
new_item.setAttribute("type", value.typeName());
new_item.setAttribute("value", value.toString());
doc.elementsByTagName(section).at(0).appendChild(new_item);
Can anyone explain to me why I need to use createElement method ?
Thank you :)

Basically DomElement creation needs information that QDomDocument has. From Qt 4.7 documentation
Since elements, text nodes, comments, processing instructions, etc., cannot exist outside the context of a document, the document class also contains the factory functions needed to create these objects. The node objects created have an ownerDocument() function which associates them with the document within whose context they were created.
http://doc.qt.io/archives/qt-4.7/qdomdocument.html#details (third paragraph)

Related

Add a node to TTreeView in C++ Builder

It is a very simple question that I have to ask, but I couldn't find the answer anywhere.
I'm using C++ Builder XE6 and I want to use a TTreeView. I have found several tutorials about it, saying that the method to add a node is to do this :
TreeView->Items->Add(NULL, "name");
But it doesn't work, I get the error that Add() is not a member of Items. After a quick research, I have found that Add() is a method for TTreeNodes, but TreeView->Items is a TTreeViewItem. Maybe all the tutorials that I have read are outdated. Anyway, I can't find any way to do it.
Thank you for your help.
TTreeViewItem is a FireMonkey class, not a VCL class. All of the tutorials you have read are likely based on VCL.
In VCL, TTreeView::Items as a TTreeNodes object:
__property TTreeNodes* Items = {read=FTreeNodes, write=SetTreeNodes};
TTreeNodes does have an Add() method:
TTreeNode* __fastcall Add(TTreeNode* Sibling, const System::String S);
The code you showed works fine in VCL.
In FireMonkey, TTreeView::Items is an indexed array of TTreeViewItem objects:
__property TTreeViewItem* Items[int Index] = {read=GetTreeItem};
TTreeViewItem does not have an Add() method. The correct way to add a new node to a FireMonkey TTreeView is to create a TTreeViewItem object and set its Parent property, eg:
TTreeViewItem *node = new TTreeViewItem(TreeView);
node->Text = "name";
node->Parent = TreeView;
You need to call TreeView->Items->AddChild(NULL, "name"); - This will add a child node of root (NULL). If you need to add a child of a specific node then you need to pass the node as parameter.
According to the docs, and a quick check in the hpp file, Items is a TTreeNodes so Add and AddChild should work. Are you sure you're not accessing, for instance, Items[0] ?

How to make a deep copy of an entire QDomDocument

I want to create a deep copy of a QDomDocument in an xml model in order to allow the user to later restore the document to its original state. The QDomDocument documentation says that this can be achieved by using cloneNode(). However, cloneNode() returns a QDomNode, not a QDomDocument, and I can't seem to figure out how how to properly add it to a new document.
I've tried:
QDomDocument copy;
copy.importNode(existingDocument.cloneNode(true),true);
and
QDomDocument copy;
copy.appendChild(existingDocument.cloneNode(true),true);
but neither work.
If you have a QDomNode, you can use its toDocument function.
Assuming QDomNode node is the node returned from cloneNode()
QDomDocument newDocument = node.toDocument();

Is it necessary to make QDomElement created by the same QDomDocument to write XML?

I use QDomDocument to write XML document.
But in my dom tree, some nodes are created using docA, some using docB.
QDomElement parentNode = docA.CreateElement("name");//created by docA
QDomElement childNode = docB.CreateElement("value");//created by docB
parentNode.appendChild(childNode);//in onr tree
And:
QTextStream out(&file);
docA.save(out, Indent);//docA created the root QDomElement
//write the file using docA
So is it possible to write the whole tree to XML like this?
You should avoid this because things will start going wrong when if docA goes out of scope if docB is still being used. I believe what you're proposing will technically work until that occurs, but the library seems designed to discourage it.
However, there is a function QDomDocument::importNode() which is probably what you want. You can do something like this:
docAParent.appendChild( docA.importNode( docBNode, true ) );
The boolean argument controls whether or not a deep copy is made.
See the documentation: http://qt-project.org/doc/qt-4.8/qdomdocument.html#importNode

Changing a Widget's name based on a string read in from an XML form in Qt

I'm writing a code for a voting machine that will allow user to read in custom XML ballots and then vote on them, however in the current build I have in QtCreator, I don't see an easy way to edit buttons in my GUI directly. In the code snippet below, I assign an element to pull out the names and type of ballot being read in, but I need to append a label on the GUI as well as change buttons to the names of candidates read in. Any ideas on how to do this?
while(!n.isNull()){
QDomNode x = n.firstChildElement();
QDomElement e = n.toElement();
QMessageBox::information(0,
tr( "Loading Element" ),
tr( "Our element is %1" ).arg(e.tagName()) );
QDomElement p = x.firstChildElement();//p finds Races
QMessageBox::information(0,tr("Foo"),tr("p = %1").arg(p.text()));//finds Race and Ballot types
n = n.nextSibling();
}
}
All the widgets you created using the Designer UI are available from your code. How to access them depends on how you linked your UI with the rest of your classes (see http://doc.qt.io/archives/4.6/designer-using-a-ui-file.html) but if you used the multiple inheritance approach your widgets and layouts will be accessible directly from your class using the name under which they appear in Designer. Qt Creator's completion will even work with them.
Having that in mind you can easily use the usual methods to change a widget's name, add a label to a layout, etc.
If this is still unclear, please add the code you use to embed your GUI, as it is needed in order to give you a sensible code example.

How do I append elements with duplicate names using MSXML & C++?

I am write some code to update a XML DOM using MSXML4 & C++. I need a method that appends a child element to a parent element. The code I have written below works until the title of the child matches the title of another child under the parent. I cannot change the title of the children so I need to find a way to append them to the parent.
Can anyone provide some guidance?
// this call creates '<parent><child/></parent>'
AppendChild("/root/parent", "child");
// this call attempts to create '<parent><child/><child/></parent>' but the DOM remains unchanged ('<parent><child/></parent>')
AppendChild("/root/parent", "child");
void AppendChild(const std::string kPathOfParent, const std::string kNameOfChild)
{
MSXML2::IXMLDOMNodePtr pElement = m_pXmlDoc->createNode(NODE_ELEMENT, kNameOfChild.c_str(), m_xmlns.c_str());
MSXML2::IXMLDOMNodePtr pParent = m_pXmlDoc->selectSingleNode(kPathOfParent.c_str());
MSXML2::IXMLDOMNodePtr pNewChild = pParent->appendChild(pElement);
}
I am not sure exactly what the problem was, but somewhere my binaries were out of step. I rebuilt the entire project via 'Clean Solution' instead of just the 'Build Solution' option. Now both children are created using the code above. It is not clear to me why I was able to step in to the code via the debugger, but the second child was never created until I cleaned the solution.
Jeff & Remy, thank-you for your comments.