I do use the QtXML Module providing a "nice" DOM-Model for Qt.
The problem i encounter is, one cannot concatenate the calls making one require to create extra QDomElement variables for appending. Is there a way around this?
QDomDocument doc;
QDomProcessingInstruction xmlVers = doc.createProcessingInstruction("xml","version=\"1.0\" encoding='utf-8'");
doc.appendChild(xmlVers);
QDomElement docTool = doc.createElement("tool");
doc.appendChild(docTool);
QDateTime t = QDateTime::currentDateTime();
QString dateString = t.toString("yyyy-MM-ddTHH:mm:ss");
// 0: Correct implementation requiring extra QDomElement dateElement
QDomElement dateElement = doc.createElement("date");
dateElement.appendChild(doc.createTextNode(dateString));
docTool.appendChild(dateElement);
// 1: Concatenating create* calls without extra variable
docTool.appendChild(doc.createElement("date1").appendChild(doc.createTextNode(dateString)));
// 2: Trying to encapsulate createElement call by brackets
docTool.appendChild((((QDomElement)doc.createElement("date2")).appendChild(doc.createTextNode(dateString))));
// 3: Trying to hit the nail by elementById (Broken per documentation?!)
docTool.appendChild(doc.createElement("date3"));
doc.elementById("date3").appendChild(doc.createTextNode(dateString));
ui->textBrowser->append(doc.toString());
Giving really strange results:
<?xml version="1.0" encoding='utf-8'?>
<tool>
<date>2015-01-21T10:33:56</date>2015-01-21T10:33:562015-01-21T10:33:56<date3/>
</tool>
As we see
0: is correct
1: has no date tag at all
2: same as before
3: has the date tag but no textnode content
Why can one not concatenate these calls?
appendChild() returns the node that was added. So in:
docTool.appendChild(doc.createElement("date1").appendChild(doc.createTextNode(dateString)));
you end up trying to append the text node to both the date1 element and the docTool element. This should work:
docTool.appendChild(doc.createElement("date1")).appendChild(doc.createTextNode(dateString));
I think the key is in the following sentence (Qt docs):
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.
When you create a local object with
QDomElement dateElement = doc.createElement("date");
the dateElement element is a reference of the internal tree node. Deleting this object will delete the internal object it refer to. It happens in the following call:
docTool.appendChild(doc.createElement("date1").appendChild(doc.createTextNode(dateString)));
where temporary object created by the doc.createElement("date1") call get deleted as soon as the function called, thus the referenced internal element is also get deleted.
Related
I am writing code that needs to return a modified version of an XML node, without changing the original node in the parent document.
How can I copy/clone the node so that the original context will not be connected to/affected by it? I don't want changes made to this node to change the original node in the parent document, just to the copy that my function is returning.
What I'm looking for would be very similar to whatever cts:highlight is doing internally:
Returns a copy of the node, replacing any text matching the query
with the specified expression. You can use this function to easily
highlight any text found in a query. Unlike fn:replace and other
XQuery string functions that match literal text, cts:highlight matches
every term that matches the search, including stemmed matches or
matches with different capitalization. [marklogic docs > cts:highlight]
The easiest way to create a clone/copy of a node is to use the computed document node constructor:
document{ $doc }
If you are cloning a node that is not a document-node(), and don't want a document-node(), just a clone of the original node(), then you can XPath to select that cloned node from the new document-node():
document{ $foo }/node()
Just for completeness: in general, the standard XQuery Update Facility has copy-modify expressions that explicitly perform a copy. With no modifications, this is like explicit cloning.
copy $node := $foo
modify ()
return $node
I am not sure if MarkLogic supports this syntax or not though. As far as I know, it uses its own function library for updates.
In-memory XML nodes are not directly modifiable. Instead, you make your desired changes while constructing a new node. If you know XSLT, that can be a good way to do it. If not, you can use an XQuery technique called recursive descent.
I have a little problem in my program. I have a config file put in settings. I pull from it the names of the object I need to be checked (these are QCheckBox).
I have this piece of code (It compiles and runs but when it's at "cBox->setChecked" it just crash):
void Preproc::on_tBtnManual_toggled(bool checked){
if(checked){
ui->tBtnManual->setText("Systematic");
}else{
ui->tBtnManual->setText("Manual");
settings.beginGroup("Preprocessing");
QStringList keys = settings.childKeys();
foreach(QString configParam,keys){
QCheckBox *cBox = ui->gridLayout->findChild<QCheckBox *>(configParam);
cBox->setChecked(settings.value(configParam).toBool());
}
}
}
I have tried to put ui->cBox->... put it says that cBox is not a child of ui.
If I qDebug(cBox) I have a QObject(0x0) so nothing !
I'm a little new to Qt so maybe it's a simple thing.
Thanks and have a nice day :)
Are you sure that an object is found?
I don't think so (different name? wrong layout?). cBox is 0x0 when nothing is found.
However put a
if (cBox)
before
cBox->setChecked(settings.value(configParam).toBool());
and it will not crash anymore when it doesn't find an object by name.
are you sure the name (content of configParam) is correct?
you can try the search from QApplication
QApplication::instance()->findChild<QCheckBox *>(configParam);
the findChild method performs a recursive search, if the object exists in the hirachie, it will be found. if the object is not found, it could be:
the object does not exist
the object has another name
the object or one of its ancestors has no (NULL) parent
can you post the part of the .ui file with the check box? it would be helpful.
I read some QSettings from an .ini file:
QSettings* settingsDocRoot=new QSettings(_settingsFile ,QSettings::IniFormat, parent);
This is passed to some object. However, I then do a copy QSettings* s2= new QSettings(settingsDocRoot); and modify one particular value s2->setValue("path", whateverNewPath);
Basically I want to pass a slightly modified QSettings object to another object. But how do I avoid that the original ini file is updated with the changed value (s2->setValue)?
One idea was, simply to set the path to "". However, according to QSettings - where is the location of the ini file? then a default location will be assumed (OK, original file will not be changed, but unnecessary file will be written).
QSettings is entirely designed for persistence. If you don't want your copy to write to disk, you'd probably be better off copying all the values into a QHash and passing that to your other object:
QHash<QString, QVariant> hash;
const QStringList keys = settings->allKeys();
Q_FOREACH(QString key, keys) {
hash[key] = settings->value(key());
}
I am currently doing the following:
QSettings* settingsWsNaviGraph = new QSettings(settingsDocRoot);
// avoid writing to file
settingsWsNaviGraph->setPath(QSettings::InvalidFormat, QSettings::UserScope, "");
This dirty hack seems to avoid writing, at least my original file remains unchanged and I do not see any unwanted file yet (will report if I do find one).
If this here does not work, I'll try to register my own format with bogus read/write methods. See here
I'm trying to use QtConcurrent::map to run this function
//This function is used through QtConcurrent::map to create images from a QString path
void MainWindow::createQImage(QString* path) {
//create an image from the given path
QImage* t = new QImage(*path);
imageList->append(t);
}
on this container/sequence (declared in the mainwindow header and initialized in the mainwindow constructor)
QList<QImage *> *imageList = new QList<QImage *>;
Here's the code I'm trying to run
QFutureWatcher<void> futureWatcher;
futureWatcher.setFuture(QtConcurrent::map(imageList, &MainWindow::createQImage));
and here are the errors I'm getting:
request for member 'begin' in 'sequence', which is of non-class type 'QList<QImage*>*'
request for member 'end' in 'sequence', which is of non-class type 'QList<QImage*>*'
I need the "createQImage" function to be run for every element in "imageList," which can reach into the thousands. I believe the problem to be with the first parameter to the map function. And from what I've read, it may have to do with compatibility. There isn't much sample code online that I was able to relate to. I'm new to Qt and not the most experienced of programmers but I'd appreciate some help and feedback.
Alternatively, is there better way to do this using QtConcurrent?
Thanks in advance!
QtConcurrent::map wants a sequence as its first argument. You passed it a pointer to a sequence.
If you do
futureWatcher.setFuture(QtConcurrent::map(*imageList, &MainWindow::createQImage));
it should be happy.
Note that the compiler was reasonably clear about what the problem was. Take the time to read the errors carefully, they're usually not as cryptic as they perhaps at first seem. In this case it was telling you that the argument you passed was not of a class type. A quick look at the argument type at the end of the error reveals that it is a pointer.
QList, QImage, QString are Copy-On-Write types (see other Qt implicitly shared types), so you shouldn't use pointers to these types because they are basically already smart pointers.
And if you remove all pointers from your code, it should also fix the main problem.
I need to read xml tags and its datas from one file and then write it to another xml..how to do it?? please let me know immediately...?
See http://livedocs.adobe.com/flex/2/langref/XML.html . I find it hard to believe you googled this before asking.
You can use the FileReference.save() method to save XML data to a local file. It will prompt the user for a location to save the file first and then save the data.
Here's an example:
var xml:XML = <root><someXmlTag/></root>;
var fileReference:FileReference = new FileReference()
fileReference.save(xml, "myfile.xml");
As far as I knew, Flex wasn't able to write to files!
I use a HTTPService to load the XML file and a result even handler to access it.
<mx:HTTPService id="service" url="myXml.xml" result="ServiceResult (event)"/>
Do not specify a result format in the HTTPService tag.
This is the code for the result event handler.
private function ServiceResult (e : ResultEvent) : void {
e.result.XmlTag.AnotherXmlTag;
}
You can also use service.lastResult to access the last result returned by the HTTPService. The result is fully compatible with the dataProvider property, especially in arrays and chart series.
var series : LineSeries = new LineSeries ();
series.dataProvider = e.result.XmlTag.AnotherXmlTag;
This will take the value in all AnotherXmlTag tags within XmlTag. For series, though, you should also specify either a yField or and xField, but it digress :-)
If it doesn't work, you can also cast it using the as keyword, example:
series.dataProvider = e.result.XmlTag as ArrayCollection;
I haven't actually tried casting it in this scenario, but the bottom line is that XML tags are vary compatible with arrays and ArrayCollections.
In your case, you would just use e.result to get the complete XML file, assign it to a variable, and write it using Ben's method. You can also create an array from individual values using the way I explained above, and manually insert tags and such if you need. The advantage of this is that you have all the values ready in an array would you need them later on. If you loop through the indices, this won't require a lot of work, and it would be the way I'd do it.
Hope this helps!