QXmlStream and QTableWidget read and write xml file
-
I have a tableWidget :
I read the content with this code. I know it has problem
QString mList ; for(int row = 0;row <ui->tableWidget->rowCount(); row++) { for(int column = 0;column< ui->tableWidget->columnCount() ;column++) { QTableWidgetItem *item1(ui->tableWidget->item(row,column)); if(item1) { qDebug() << ui->tableWidget->item(row,column)->text(); mList += ui->tableWidget->item(row,column)->text()+","; } } mList += "\n"; } mList.remove(QRegExp("[\n]{2}")); qDebug() << mList; }
How can i parse the data and populate in xml like this :
<words> <row ID="0" text="row1"> <col1 ID="0" text="item1"/> <col2 ID="1" text="item11"/> </row> </words>
-
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)); // no idea where you take your text="row1" attribute from 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;
-
@behruz-montazeri
The important thing to note in @VRonin's (correct) answer is that you do not first a build a string out of your table data and then parse it --- that would be madness! You produce the XML as you go along in the first place, where you already know the correct structure without having to parse anything. -
@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?
-
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....
-
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.
-
@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