QXmlStream and QTableWidget read and write xml file
-
@behruz-montazeri Can you show us your code?
-
Maybe there's a bug because items i added in Qtcreator gui are in the file but when i add another records last one is empty "" .
#include "mainwindow.h" #include "ui_mainwindow.h" #include <QDebug> #include <QtXml> #include <QTextStream> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); ui->tableWidget->horizontalHeader()->setStretchLastSection(true); ui->tableWidget->setColumnWidth(0,this->width()/2); ui->tableWidget->setColumnWidth(1,this->width()/2); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_action_Save_triggered() { QString result; QXmlStreamWriter writer(&result); writer.setAutoFormatting(true); writer.writeStartElement(QStringLiteral("words")); for(int i=0, maxRow = ui->tableWidget->rowCount();i<maxRow ;++i){ writer.writeStartElement(QStringLiteral("row")); writer.writeAttribute(QStringLiteral("ID"),QString::number(i)); for(int j=0, maxCol = ui->tableWidget->columnCount();j<maxCol ;++j){ writer.writeStartElement(QStringLiteral("col%1").arg(j+1)); writer.writeAttribute(QStringLiteral("ID"),QString::number(j)); writer.writeAttribute(QStringLiteral("text"),ui->tableWidget->model()->index(i,j).data().toString()); writer.writeEndElement(); //col } writer.writeEndElement(); //row } writer.writeEndElement(); //words qDebug() << result; QFile file("/home/behruz/Qt/TestPro/my.xml"); if(!file.open(QIODevice::WriteOnly | QIODevice::Text)) { qDebug() << "Open the file for writing failed"; } else { QTextStream stream(&file); stream << result; file.close(); qDebug() << "Writing is done"; } }
-
QXmlStreamWriter
can operate directly on aQIODevice
(likeQFile
), no need to put a string in the middle and useQTextStream
. Your code crates a big inconsistency with encodings if you usewriteStartDocument
-
when i add another records last one is empty
How do you add them?
-
behruz montazerireplied to VRonin on 6 Sept 2018, 15:58 last edited by behruz montazeri 9 Jun 2018, 16:14
When i run the program and add some record to QTableWidget the last one won't write to file.
<words> <row ID="0"> <col1 ID="0" text="item 1"/> <col2 ID="1" text="item 11"/> </row> <row ID="1"> <col1 ID="0" text="item 2 "/> <col2 ID="1" text="item 22"/> </row> <row ID="2"> <col1 ID="0" text="item 3"/> <col2 ID="1" text="item 33"/> </row> <row ID="3"> <col1 ID="0" text="a"/> <col2 ID="1" text="b"/> </row> <row ID="4"> <col1 ID="0" text="c"/> <col2 ID="1" text="d"/> </row> <row ID="5"> <col1 ID="0" text="e"/> <col2 ID="1" text=""/> </row>
-
I want the reverse functionality to read the file and add to QTableWidget i tried but i couln't :
QFile file( "/home/behruz/Qt/TestPro/my.xml" ); if( !file.open( QFile::ReadOnly | QFile::Text ) ) { // print error cannot open } QXmlStreamReader reader; reader.setDevice( &file ); reader.readNext(); if (reader.readNextStartElement()) { if (reader.name() == "words"){ while(reader.readNextStartElement()){ if(reader.name() == "col1"){ QString s = reader.readElementText(); qDebug(qPrintable(s)); } } } }
-
@behruz-montazeri
Compare your code here line for line against your code above for outputting the XML.writer.writeAttribute(QStringLiteral("text"),ui->tableWidget->model()->index(i,j).data().toString());
shows you are storing
text
as an attribute (text="item1"
).That does not pair with your
QString s = reader.readElementText();
which will be the text inside each element, where you store nothing....
-
behruz montazerireplied to JonB on 6 Sept 2018, 16:41 last edited by behruz montazeri 9 Jun 2018, 16:59
QFile file("/home/behruz/Qt/TestPro/my.xml"); if (file.open(QIODevice::ReadOnly)) { QXmlStreamReader reader(file.readAll()); file.close(); while(!reader.atEnd()) { reader.readNext(); if (reader.isStartElement()) { if (reader.name() == "words") { reader.readNextStartElement(); if(reader.name() == "row"){ reader.readNextStartElement(); foreach(const QXmlStreamAttribute &attr, reader.attributes()) { if (attr.name().toString() == QLatin1String("text")) { QString attribute_value = attr.value().toString(); qDebug(qPrintable(attribute_value)); } } } } } } }
It only shows the item 1 how populate it in QTableWidget ?
-
@behruz-montazeri
Again, compare your reader against the writer code you have. That loops round every row, doesn't it? But your reader only has anif (reader.name() == "words")
. Plus I don't see anything looping over the<col...>
elements at all. And you say it only shows the first item (first row & column). Do you think that could be related to no loops?I'm not going to write it for you. You need to look up the docs and read the necessary elements in the necessary loops. You're headed in the right direction, just think about where your code needs to loop and read what to get back to what you had for the writing code.
-
@JonB
What's the loop statement ? I know it needs a loop but i can't find where and how. -
@behruz-montazeri
Loop statements arefor
,while
,foreach
. The writer usedfor
s because it knew how many rows & columns there were. You'll probably wantwhile
s in the reader, certainly to move through all the<row>
elements. -
@JonB
I already used a loop :foreach(const QXmlStreamAttribute &attr, reader.attributes()) { if (attr.name().toString() == QLatin1String("text")) { stList.append( attr.value().toString()); qDebug() << stList; }
But it seems it only works for one record. Give me the code or a real hint. Thanks.
-
@behruz-montazeri said in QXmlStream and QTableWidget read and write xml file:
QXmlStreamReader reader(file.readAll());
??? This makes no sense, it should be
QXmlStreamReader reader(&file);
I guess -
I corrected reading by using two loops.
QStringList stList; QFile file("/home/behruz/Desktop/Temp/QTableWidgetXml/my.xml"); if( !file.open( QFile::ReadOnly | QFile::Text ) ) { // print error cannot open } QXmlStreamReader reader(&file); while(!reader.atEnd()) { reader.readNext(); if (reader.isStartElement()) { reader.readNextStartElement(); for(int i=0;i<ui->tableWidget->rowCount();i++){ if(reader.name() == "row"){ reader.readNextStartElement(); for(int i=0;i<2;i++){ // qDebug() << reader.name(); foreach(const QXmlStreamAttribute &attr, reader.attributes()) { if (attr.name().toString() == QLatin1String("text")) { stList.append( attr.value().toString()); qDebug() << stList; } } reader.readNextStartElement(); reader.readNextStartElement(); } } reader.readNextStartElement(); } } } for(int i=0, maxRow = ui->tableWidget->rowCount();i<maxRow ;++i){ for(int j=0, maxCol = ui->tableWidget->columnCount();j<maxCol ;++j){ QTableWidgetItem *newItem = new QTableWidgetItem(tr("%1").arg( stList[L])); qDebug() << stList[i]; ui->tableWidget->setItem(i, j, newItem); L++; } }
-
maybe the
XmlModelSerialiserPrivate::writeXmlElement
andXmlModelSerialiserPrivate::readXmlElement
methods from https://github.com/VSRonin/QtModelUtilities/blob/master/src/xmlmodelserialiser.cpp might help
15/19