Checking if root element exist in Xml using qt c++ - c++

I have an Xml file:
<?xml version="1.0" encoding="utf-8" ?>
<AppConfig>
<DefaultCulture></DefaultCulture>
<StartupMessageTitle></StartupMessageTitle>
<StartupMessageText></StartupMessageText>
<StartupMessageIcon>Information</StartupMessageIcon>
<DefaultProfileSettings>
<DriverName>wia</DriverName>
<UseNativeUI>false</UseNativeUI>
<IconID>0</IconID>
<MaxQuality>false</MaxQuality>
<AfterScanScale>OneToOne</AfterScanScale>
<Brightness>0</Brightness>
<Contrast>0</Contrast>
<BitDepth>C24Bit</BitDepth>
<PageAlign>Left</PageAlign>
<PageSize>Letter</PageSize>
<Resolution>Dpi100</Resolution>
<PaperSource>Glass</PaperSource>
</DefaultProfileSettings>
<!--
<AutoSaveSettings>
<FilePath></FilePath>
<ClearImagesAfterSaving>false</ClearImagesAfterSaving>
<Separator>FilePerPage</Separator>
</AutoSaveSettings>
-->
</AppConfig>
I need to check if root elements "AutoSaveSettings" exists in xml using qt c++ . if the root elements exists then remove the commented line before and after the Auto save settings? How can we do it in qt c++. How do I perform this operation in c++.Check if exists start element or root element
#include <QtCore>
#include <QtXml/QDomDocument>
#include <QDebug>
#include <QFile>
#include <QXmlStreamReader>
bool elementExists(const QFile &file, const QString &elementName)
{
QXmlStreamReader reader(&file);
while (reader.readNextStartElement())
{
if(reader.name() == elementName)
{
return true;
}
}
return false;
}
int main(int argc,char *argv[])
{
QCoreApplication a(argc,argv);
QDomDocument document;
QFile file = "C:/Program Files (x86)/NAPS2/appsettings.xml";
if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
{
qDebug()<<"Failed to open the file";
return -1;
}
else{
if(!document.setContent(&file))
{
qDebug()<< "Failed to load Document";
return -1;
}
file.close();
}
elementExists(file,"AutoSaveSettings");
qDebug()<< "Finished";
return a.exec();
}

Try something like this :
bool elementExists( QFile & file, const QString & elementName){
QXmlStreamReader reader (&file);
while (reader.readNextStartElement()){
if(reader.name() == elementName) return true;
//elementName should be "AutoSaveSettings"
}
return false;
}
Edit : an alternative way could be using QDomDocument
Not recomanded because QDomDocument is not actively maintained anymore
bool elementExists( QFile & file,const QString & elementName){
QDomDocument reader;
reader.setContent(&file, true);
QDomNodeList elementList = reader.elementsByTagName(elementName);
return elementList.size()>0;
}

Related

Last 52 lines are not written in csv file using qt

I have one csv file in which 3 column and 866300 lines. I have try to write this data into other csv file. when i try to write it has write 866248 lines in file after that remaining 52 lines are not write in file. what is the problem I do not understand it. I have try to debug this problem using print that data on console then it has print till last line on the console. only the problem in write the data in file.
#include <QCoreApplication>
#include <QFile>
#include <QStringList>
#include <QDebug>
#include <QTextStream>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QFile file("C:/Users/hello/Downloads/hello.csv");
QFile write("new_data.csv");
if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
{
qDebug()<<file.errorString();
return 1;
}
if(!write.open(QIODevice::WriteOnly |QIODevice::Append))
{
qDebug()<<file.errorString();
return 1;
}
QTextStream out(&write);
QStringList data;
while (!file.atEnd())
{
QString line = file.readLine();
data = line.split(',');
if (data[0]=="v1")
{
out<<line;
continue;
}
else
{
int seq = (data[0].toInt())-1;
QString str = QString::number(seq)+","+data[1]+","+data[2].trimmed();
qDebug()<<str;
out<<str<<"\n";
}
}
return a.exec();
}
please help.
Please close the file before the return a.exec(); this line and after the while loop. add this line below line.
write.close();

Count File in a folder (include subfolder)

hi i use Qt and i want to know how much file are in a folder (include subfolder)
i find some code in internet but all of them only count file in a folder and not its subfolder
like this codes
#include <stdio.h>
#include <dirent.h>
int main(int argc, char *argv[])
{
if(argc != 2)
{
printf("Usage: ./count \"<path>\"\n");
return 1;
}
struct dirent *de;
DIR *dir = opendir(argv[1]);
if(!dir)
{
printf("opendir() failed! Does it exist?\n");
return 1;
}
unsigned long count=0;
while(de = readdir(dir))
{
++count;
}
closedir(dir);
printf("%lu\n", count);
return 0;
}
i find this code here, it only count file in a folder and not its subfoler
anyone can help me
edit 1
i test this code from this page, it working but it can edit for less cpu usage?
sumit_smk code is ok but its need a little edit for your case
here is the code you can use
int file = 0;
QDirIterator it("/Your_folder/", QDir::Files, QDirIterator::Subdirectories);
while (it.hasNext())
{
if(it.next() > 0 )
{
file++;
}
}
qDebug() << file;
The following code runs for Qt.
QStringList nameFilters;
nameFilters << "*.jpg";
QDirIterator it(QDir::currentPath(), nameFilters, QDir::Files, QDirIterator::Subdirectories);
while (it.hasNext()) {
qDebug() << it.next();
}
use nameFilters << "*";if you want to know all the files in the parent directory and its sub-directories.

Qt - Why unable read file using QFile with directory which get from FileDialog?

I'm reading a file on Qt 5.12 using QFile. I try to read a file from my computer but when I using the directory which read from FileDialog has "file:///" prefix. Can anyone tell me why is it wrong and how to using URL which gets form FileDialog, please?
Thanks!
QFile file("C:/Users/HuuChinhPC/Desktop/my_txt.txt"); // this work
//QFile file("file:///C:/Users/HuuChinhPC/Desktop/my_txt.txt"); //didn't work
QString fileContent;
if (file.open(QIODevice::ReadOnly) ) {
QString line;
QTextStream t( &file );
do {
line = t.readLine();
fileContent += line;
} while (!line.isNull());
file.close();
} else {
emit error("Unable to open the file");
return QString();
}
FileDialog returns a url since in QML that type of data is used, but QFile not so you must convert the QUrl to a used string toLocalFile():
Q_INVOKABLE QString readFile(const QUrl & url){
if(!url.isLocalFile()){
Q_EMIT error("It is not a local file");
return {};
}
QFile file(url.toLocalFile());
QString fileContent;
if (file.open(QIODevice::ReadOnly) ) {
QString line;
QTextStream t( &file );
do {
line = t.readLine();
fileContent += line;
} while (!line.isNull());
file.close();
return fileContent;
} else {
Q_EMIT error("Unable to open the file");
return {};
}
}
*.qml
var text = helper.readFile(fileDialog.fileUrl)
console.log(text)
You have to strip the file prefix to use the URL which gets form FileDialog:
QFile file("file:///C:/Users/HuuChinhPC/Desktop/my_txt.txt")
if (Qt.platform.os === "windows") {
return file.replace(/^(file:\/{3})|(file:)|(qrc:\/{3})|(http:\/{3})/,"")
}
else {
return file.replace(/^(file:\/{2})|(qrc:\/{2})|(http:\/{2})/,"");
}

Custom class to XML using QSettings

I'd like to save custom class to XML using QSettings. But I always get XML without structure members.
#include <QCoreApplication>
#include <QtCore/qdatastream.h>
#include <qxmlstream.h>
#include <qdebug.h>
#include <QtCore/QSettings>
#include <QMetaType>
struct Interface_struct
{
QString name;
QString ip;
};
Q_DECLARE_METATYPE(Interface_struct)
QDataStream& operator <<(QDataStream& out, const Interface_struct& s)
{
out << s.name << s.ip;
return out;
}
QDataStream& operator >>(QDataStream& in, Interface_struct& s)
{
in >> s.name;
in >> s.ip;
return in;
}
static bool readXmlFile(QIODevice &device, QSettings::SettingsMap &map)
{
qDebug()<< "read";
QXmlStreamReader reader(&device);
QString key;
while(!reader.atEnd())
{
reader.readNext();
if( reader.isStartElement() && reader.tokenString() != "Settings")
{
if( reader.text().isNull() )
{
// key = Settings
if(key.isEmpty())
{
key = reader.tokenString();
}
// key = Settings/Intervall
else
{
key += "/" + reader.tokenString();
}
}
else
{
map.insert(key, reader.text().data());
}
}
}
return true;
}
static bool writeXmlFile(QIODevice &device, const QSettings::SettingsMap &map)
{
qDebug()<< "write";
QXmlStreamWriter writer(&device);
writer.writeStartDocument("1.0");
writer.writeStartElement("Settings");
foreach(QString key, map.keys())
{
foreach(QString elementKey, key.split("/"))
{
writer.writeStartElement(elementKey);
}
writer.writeCharacters(map.value(key).toString());
writer.writeEndElement();
}
writer.writeEndElement();
writer.writeEndDocument();
return true;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qRegisterMetaType<Interface_struct>("Interface_struct");
qRegisterMetaTypeStreamOperators<Interface_struct>("Interface_struct");
{
Interface_struct s;
s.name = QString("br03000");
s.ip = QString("172.16.222.5");
const QSettings::Format xml_format =
QSettings::registerFormat("xml", readXmlFile, writeXmlFile);
if(xml_format == QSettings::InvalidFormat)
{
qDebug() << "InvalidFormat!";
return 0;
}
QSettings::setPath(xml_format, QSettings::UserScope, "/home/farit/test/");
QSettings settings(xml_format, QSettings::UserScope, "xml_cfg");
settings.setValue("network", QVariant::fromValue(s));
}
{
QSettings::Format xml_format =
QSettings::registerFormat("xml", readXmlFile, writeXmlFile);
QSettings::setPath(xml_format, QSettings::UserScope, "/home/farit/test/");
QSettings settings(xml_format, QSettings::UserScope, "xml_cfg");
QVariant value = settings.value("network");
Interface_struct interface = value.value<Interface_struct>();
qDebug() << "TEST: " << interface.name << interface.ip;
}
return 0;
}
I get this output:
read
write
read
TEST: "" ""
Press <RETURN> to close this window...
And XML looks like this:
<?xml version="1.0" encoding="UTF-8"?><Settings><network></network></Settings>
How can I save structure members of custom class to XML using QSettings?
UPDATE: I'm sorry, I forgot to mention, that is supposed to be done in Qt4.

How to remove a nested tag from XML doc using QDomDocument

I need to remove a nested multilevel (unknown depth) tag from a XML file using QDomDocument. What is the proper way of doing this?
Here is a sample of XML file
<A>
<B>
<C>
.............................
</C>
</B>
</A>
I would not even use QDomDocument, aka. QtXml for this as the stream reader and writer classes are relatively simple to use in QtCore. Here goes my solution that could be further extended to support other things, too:
QtCore
testin.xml
<A>
<B>
<C>
.............................
</C>
</B>
</A>
testout.xml
<?xml version="1.0" encoding="UTF-8"?>
<A>
<B/>
</A>
main.cpp
#include <QXmlStreamReader>
#include <QXmlStreamWriter>
#include <QDebug>
#include <QString>
#include <QFile>
int main()
{
QFile inputFile("testin.xml");
if (!inputFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
qDebug() << "File open error:" << inputFile.errorString();
return 1;
}
QFile outputFile("testout.xml");
if (!outputFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
qDebug() << "File open error:" << outputFile.errorString();
return 1;
}
QXmlStreamReader inputStream(&inputFile);
QXmlStreamWriter outputStream(&outputFile);
outputStream.setAutoFormatting(true);
outputStream.writeStartDocument();
bool ignore = false;
static const QString searchString = "C";
while (!inputStream.atEnd() && !inputStream.hasError())
{
inputStream.readNext();
if (inputStream.isStartElement()) {
QString name = inputStream.name().toString();
if (name != searchString && !ignore)
outputStream.writeStartElement(name);
else
ignore = true;
} else if (inputStream.isEndElement()) {
if (!ignore)
outputStream.writeEndElement();
if (inputStream.name().toString() == searchString)
ignore = false;
}
}
outputStream.writeEndDocument();
return 0;
}
main.pro
TEMPLATE = app
TARGET = main
QT = core
SOURCES += main.cpp
Build and Run
qmake && make && ./main
QtXml
If you still insist on using QtXml for this simple task, you could do this:
main.cpp
#include <QDomDocument>
#include <QDomNode>
#include <QDomElement>
#include <QFile>
#include <QDebug>
int main()
{
QFile inputFile("testin.xml");
if (!inputFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
qDebug() << "File open error:" << inputFile.errorString();
return 1;
}
QDomDocument doc;
doc.setContent(&inputFile);
QDomNode searchNode = doc.elementsByTagName("C").item(0);
QDomNode parentNode = searchNode.parentNode();
parentNode.removeChild(searchNode);
qDebug() << doc.toString();
return 0;
}
main.pro
TEMPLATE = app
TARGET = main
QT = core xml
SOURCES += main.cpp
Build and Run
qmake && make && ./main
Output
"<A>
<B/>
</A>
"