How can deal with such xml files?



  • Wish you can help me with two problems!
    1.How can I read the size information in such xml files ?
    2.How can I generate such xml files?

    0_1500775170959_1.jpg



  • @Geng.Y
    Hi,friend,welcome.

    1. you can search key words of Qt QXml, you will get some Qt class about xml .
    2. here are some demos about how to process xml file in qt. link


  • I find it really complex to deal with xml files, but let me try!
    Thank you!



  • @joeQ
    I‘ve tried to read four values from the 0.xml,xmin,ymin,xmax and ymax in "bndbox", and tp draw a rectangle with them.But it doesn't work. I've debuged only to find that I cannot get those values, though the reader can find "bndbox" well. There must have been something wrong in small details, could you please help me to figure out?

    The class ParseXml is used in ImageWidget.

    //parsexml.h
    
    #pragma once
    #include <QXmlStreamReader>
    #include <QMessageBox>
    #include <QString>
    #include <QFile>
    class ParseXml
    {
    public:
    	ParseXml(void);
    	ParseXml(QString fileName);
    	~ParseXml(void);
    
    	void ReadFile(const QString &fileName);
    	void ReadAnnotation();
    	void ReadObject();
    	void ReadBndbox();
    	void Skip();
    
    	QPoint get_start_point();
    	QPoint get_end_point();
    
    private:
    	QXmlStreamReader reader;
    	int m_xmin;
    	int m_ymin;
    	int m_xmax;
    	int m_ymax;
    };
    
    //parsexml.cpp
    
    #include "ParseXml.h"
    
    
    ParseXml::ParseXml(void)
    {
    }
    
    ParseXml::ParseXml(QString fileName)
    {
    	ReadFile(fileName);
    }
    
    ParseXml::~ParseXml(void)
    {
    }
    
    void ParseXml::ReadFile(const QString &fileName)
    {
    	QFile file(fileName);
    
    	if (file.open(QIODevice::ReadOnly|QIODevice::Text))
    	{
    		reader.setDevice(&file);
    
    		while (!reader.atEnd())
    		{
    			if (reader.isStartElement())
    			{
    				if (reader.name()=="annotation")
    				{
    					ReadAnnotation();
    				}
    				else
    				{
    					reader.raiseError(QObject::tr("Not a valid annotation file"));
    				}
    			}
    			else
    			{
    				reader.readNext();
    			}
    		}
    
    		file.close();
    	}
    }
    
    void ParseXml::ReadAnnotation()
    {
    	reader.readNext();
    
    	while(!reader.atEnd())
    	{
    		if (reader.isEndElement())
    		{
    			reader.readNext();
    			break;
    		}
    
    		if (reader.isStartElement())
    		{
    			if (reader.name()=="object")
    			{
    				ReadObject();
    			}
    			else
    			{
    				Skip();
    			}
    		}
    		else
    		{
    			reader.readNext();
    		}
    	}
    }
    
    void ParseXml::ReadObject()
    {
    	reader.readNext();
    
    	while (!reader.atEnd())
    	{
    		if (reader.isEndElement())
    		{
    			reader.readNext();
    			break;
    		}
    
    		if (reader.isStartElement())
    		{
    			if (reader.name()=="bndbox")
    			{
    				ReadBndbox();
    			}
    			else
    			{
    				Skip();
    			}
    		}
    		else
    		{
    			reader.readNext();
    		}
    	}
    }
    
    void ParseXml::ReadBndbox()
    {
    	int points[4];
    
    	for (int i=0;i<4;i++)
    	{
    		reader.readNext();
    		points[i] = reader.readElementText().toInt();
    		reader.readNext();
    	}
    
    	m_xmin = points[0];
    	m_ymin = points[1];
    	m_xmax = points[2];
    	m_ymax = points[3];
    }
    
    void ParseXml::Skip()
    {
    	reader.readNext();
    
    	while(!reader.atEnd())
    	{
    		if (reader.isEndElement())
    		{
    			reader.readNext();
    			break;
    		}
    
    		if (reader.isStartElement())
    		{
    			Skip();
    		}
    		else
    		{
    			reader.readNext();
    		}
    	}
    }
    
    QPoint ParseXml::get_start_point()
    {
    	return QPoint(m_xmin,m_ymin);
    }
    
    QPoint ParseXml::get_end_point()
    {
    	return QPoint(m_xmax,m_ymax);
    }
    
    //imagewidget.h
    
    #ifndef IMAGEWIDGET_H
    #define IMAGEWIDGET_H
    
    #include <QWidget>
    #include <QImage>
    #include <vector>
    #include <QPainter>
    #include <QFileDialog>
    #include <QMouseEvent>
    #include <QMessageBox>
    #include <QXmlStreamReader>
    #include <QToolTip>
    #include "ui_imagewidget.h"
    #include "Rect.h"
    #include "ParseXml.h"
    
    using namespace std;
    
    class ImageWidget : public QWidget
    {
    	Q_OBJECT
    
    public:
    	ImageWidget(QWidget *parent = 0);
    	~ImageWidget();
    
    public slots:
    	void Open();
    	void Save();
    	void SaveAnnotation();
    	void ReadXml();
    	void SaveXml();
    	void Delete();
    	void paintEvent(QPaintEvent *);
    	void mousePressEvent(QMouseEvent *event);
    	void mouseMoveEvent(QMouseEvent *event);
    	void mouseReleaseEvent(QMouseEvent *event);
    
    private:
    	Ui::ImageWidget ui;
    
    	
    	QImage *ptr_image;
    	QImage *ptr_save;
    	QPoint m_Start;
    	QPoint m_End;
    	bool draw_status;
    	bool load_status;
    	vector<Rect*> rect_array;
    
    
    };
    
    #endif // IMAGEWIDGET_H
    
    
    //imagewidget.cpp
    
    #include "imagewidget.h"
    
    ImageWidget::ImageWidget(QWidget *parent)
    	: QWidget(parent)
    {
    	ui.setupUi(this);
    
    	ptr_image = new QImage();
    	ptr_save = new QImage();
    	draw_status = false;
    	load_status = false;
    	setMouseTracking(true);
    	
    }
    
    ImageWidget::~ImageWidget()
    {
    	for (int i=0;i<rect_array.size();i++)
    	{
    		if (rect_array[i])
    		{
    			delete rect_array[i];
    			rect_array[i] = NULL;
    		}
    	}
    }
    
    void ImageWidget::Open()
    {
    	QString fileName = QFileDialog::getOpenFileName(this,tr("Read Image"),".",tr("Image(*.bmp *.png *.jpg)"));
    
    	if (!fileName.isEmpty())
    	{
    		ptr_image->load(fileName);
    		load_status = true;
    		 
    	}
    
    	update();
    }
    
    void ImageWidget::Save()
    {
    	QString fileName = QFileDialog::getSaveFileName(this,tr("Save Image"),".",tr("Image(*.bpm *.png *.jpg)"));
    
    	if (!fileName.isEmpty())
    	{
    		ptr_save->save(fileName);
    		
    	}
    }
    
    void ImageWidget::SaveAnnotation()
    {
    
    }
    
    void ImageWidget::ReadXml()
    {
    	QString fileName = QFileDialog::getOpenFileName(this,tr("Read Xml File"),".",tr("Xml(*.xml)"));
    	ParseXml parsexml_(fileName);
    	m_Start = parsexml_.get_start_point();
    	m_End = parsexml_.get_end_point();
    }
    
    void ImageWidget::SaveXml()
    {
    	QString fileName = QFileDialog::getSaveFileName(this,tr("Save Xml File"),".",tr("Xml(*.xml)"));
    }
    
    void ImageWidget::Delete()
    {
    	if (!rect_array.empty())
    	{
    		rect_array.pop_back();
    	}
    }
    
    void ImageWidget::mousePressEvent(QMouseEvent *event)
    {
    	if (Qt::LeftButton==event->button()&&load_status)
    	{
    		draw_status = true;
    		m_Start = m_End = event->pos();
    	}
    }
    
    void ImageWidget::mouseMoveEvent(QMouseEvent *event)
    {
    	QToolTip::showText(event->globalPos(),QString::number( event->pos().x() ) + ", " +QString::number( event->pos().y() ),this, rect() );
    	QWidget::mouseMoveEvent(event);
    	
    	if (draw_status)
    	{
    		m_End = event->pos();
    	}
    }
    
    void ImageWidget::mouseReleaseEvent(QMouseEvent *event)
    {
    	Rect *current_rect = NULL;
    	current_rect = new Rect(m_Start,m_End);
    	rect_array.push_back(current_rect);
    	draw_status = false;
    }
    
    void ImageWidget::paintEvent(QPaintEvent *)
    {
    	*ptr_save = *ptr_image;
    	QPen pen;
    	QPainter painter(this);
    	QPainter paintImage(ptr_save);
    	QRect image_rect(0,0,ptr_image->width(),ptr_image->height());
    
    	
    	pen.setWidth(5);
    	pen.setColor(Qt::red);
    	painter.setPen(pen);
    	paintImage.setPen(pen);
    
    	painter.begin(this);
    	paintImage.begin(ptr_save);
    	painter.drawImage(image_rect,*ptr_image);
    
    	painter.drawRect(m_Start.rx(),m_Start.ry(),m_End.rx()-m_Start.rx(),m_End.ry()-m_End.ry());
    
    	for (int i=0;i<rect_array.size();i++)
    	{
    		rect_array[i]->Draw(painter);
    		rect_array[i]->Draw(paintImage);
    	}
    	
    	if (draw_status)
    	{
    		painter.drawRect(m_Start.rx(),m_Start.ry(),m_End.rx()-m_Start.rx(),m_End.ry()-m_Start.ry());
    		paintImage.drawRect(m_Start.rx(),m_Start.ry(),m_End.rx()-m_Start.rx(),m_End.ry()-m_Start.ry());
    	}
    
    	painter.end();
    	update();
    
    }
    


  • @Geng.Y

    Hi, I found your error. below the code, you will know where are you wrong.

    void ParseXml::ReadBndbox()
    {
        bool bOk;
        int points[4];
    
        reader.readNext(); ///< Note: here, skip the '\n' some characters
        for (int i=0;i<4;i++)
        {
            bOk = false;
            reader.readNext();
            points[i] = reader.readElementText().toInt(&bOk);
            if(!bOk){
                qDebug("toInt data failed");
            }
            reader.readNext();
        }
    
        m_xmin = points[0];
        m_ymin = points[1];
        m_xmax = points[2];
        m_ymax = points[3];
        qDebug("%d %d %d %d\n",m_xmin,m_ymin,m_xmax,m_ymax);
    }
    

    If i modified the xml file format, the code has error.

            <bndbox><xmin>144</xmin> ///< not has '\n' ,will has error
                <ymin>485</ymin>
                <xmax>164</xmax>
                <ymax>515</ymax>
            </bndbox>
    

    QXmlStream* => io stream



  • @Geng.Y Hi, friend.

    I write the code in my way. it maybe safer than your code.

    void ParseXml::ReadBndbox()
    {
        if(reader.name() == "bndbox"){
            reader.readNext();
        }else{
           /// maybe return false at here.
        }
    
        while(!reader.isStartElement()){
            reader.readNext();
        }
    
        m_xmin = ReadItemPos("xmin");
        m_ymin = ReadItemPos("ymin");
        m_xmax = ReadItemPos("xmax");
        m_ymax = ReadItemPos("ymax");
        Q_ASSERT(m_xmin >= 0 && m_ymin >= 0);
        Q_ASSERT(m_xmax >= 0 && m_ymax >= 0);
        qDebug("%d %d %d %d",m_xmin,m_ymin,m_xmax,m_ymax);
    }
    
    int ParseXml::ReadItemPos(QString itemName)
    {
        int nVal = -1;
        bool bOk;
        while(!reader.isStartElement()){
            reader.readNext();
        }
    
        if(reader.name() == itemName){
            nVal = reader.readElementText().toInt(&bOk);
            Q_ASSERT(bOk == true);
            reader.readNext();
        }
    
        return nVal;
    }
    
    


  • Thank you very much, I'm still puzzled about the "reader.readNext()"0_1500812056968_QQ截图20170723200923.jpg

    And I can't find the output of qDebug. It should be in the output window, right? But my output window is constantly emitting such kind of informations.0_1500812242091_QQ截图20170723201610.jpg



  • @Geng.Y

    ok,let's to see the function readNext.

    TokenType QXmlStreamReader::readNext()
    Reads the next token and returns its type.

    1. what is the next token ?

    you can print the token to string.

    QString QXmlStreamReader::tokenString() const
    Returns the reader's current token as string.

    2. what is the type?

    QXmlStreamReader::NoToken
    QXmlStreamReader::Invalid
    QXmlStreamReader::StartDocument
    QXmlStreamReader::EndDocument
    QXmlStreamReader::StartElement
    QXmlStreamReader::EndElement
    QXmlStreamReader::Characters
    QXmlStreamReader::Comment
    QXmlStreamReader::DTD
    QXmlStreamReader::EntityReference
    QXmlStreamReader::ProcessingInstruction

    you should to check every type whether is you want, after you call readNext.

    from the code, readNext return Characters token type.

    QXmlStreamReader::Characters The reader reports characters in text(). If the characters are all white-space, isWhitespace() returns true. If the characters stem from a CDATA section, isCDATA() returns true.

    3. How to understanding xml tokens?

    go to here



  • Thank you very much!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.