Qt中解析xml

1 篇文章 0 订阅

Qt为xml解析提供了三种不同的解析方案:

1、QXmlStreamReader,用于读取格式良好的xml文档的快速解析器;

2、DOM(文档对象模型),将xml文件转换为应用程序可以访问的树形结构;

3、SAX(xml简单应用程序编程接口),通过虚拟函数直接向应用程序报告解析事件。

比较常用的是QXmlStreamReader和DOM,QXmlStreamReader是最简单易行的方法,只需要一个类就可以搞定;DOM是将xml转换为树形结构,然后通过相关的类读取树的各个分支的数据,这种方法用到的类较多,但是功能强大,且解析类型比较多。

本文主要介绍QXmlStreamReader的使用方法,QXmlStreamReader使用简单,但是也存在缺陷,比如它就无法解析XML1.1,但这个问题很好解决。

class XmlReader
{
	
public:
    XmlReader(QTreeWidget *treeWidget);

    bool readFile(const QStringList fileList);

private:
    void readFileTitle(const QString filename);
    void readFirstElement(QTreeWidgetItem *parent_item);
//    读取不同分支的函数
    void readDeviceInfoElement(QTreeWidgetItem *parent_item);
    void readTripInfoElement(QTreeWidgetItem *parent_item);
    void readDigStausElement(QTreeWidgetItem *parent_item);
    void readSetValElement(QTreeWidgetItem *parent_item);
    void readFaultInfoElement(QTreeWidgetItem *parent_item);
    void readDataFileSizeElement(QTreeWidgetItem *parent_item);
    void readFaultKeepingTimeElement(QTreeWidgetItem *parent_item);
    void readFaultStartTimeElement(QTreeWidgetItem *parent_item);

//  跳过未知标签
    void skipUnknownElement();

//  创建QTreeWidgetItem
    QTreeWidgetItem *createChildItem(QTreeWidgetItem *parent_item=0);

    QXmlStreamReader xml;
    QTreeWidget *treeWidget;
};

此类是将xml解析后显示在QTreeWidget中,类可以解析多个文件。
XmlReader::XmlReader(QTreeWidget *treeWidget)
    :treeWidget(treeWidget)
{
}

bool XmlReader::readFile(const QStringList fileList)
{
    if(fileList.isEmpty()){
        std::cerr<<"The file list is emty!"<<std::endl;
        return false;
    }
    int num = fileList.count();
    bool isCanRead = false;
    for(int i=0;i<num;i++){
        QString file_str = fileList.at(i);

        QFile file(file_str);
        if(!file.open(QFile::ReadOnly | QFile::Text)){
            std::cerr<<"Error: Cannot read file "<<qPrintable(file_str)
                       <<": "<<qPrintable(file.errorString())<<std::endl;

            continue;
        }
		//将xml1.1转换为xml1.0
        QString str=QString("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
        int lineno = 0;
        while (!file.atEnd())
		{
            if (lineno) {
                str += file.readLine();
            }else{//跳过第一行 
				file.readLine();
			}
            lineno++;

        }
        xml.clear();
		//将读到的文件加入到QXmlStreamReader的输入流中
        xml.addData(str);
		//多个文件中只要有一个文件读取成功,isCanRead置true
        isCanRead = true;
		//从文件路径名中提取文件名,
		QStringList dir=file_str.split("\\");
        readFileTitle(dir.last());

        file.close();
        if(xml.hasError()){
            std::cerr<<"Error: Failed to parse file "
                       <<qPrintable(file_str)<<": "
                         <<qPrintable(file.errorString())<<std::endl;
//            return false;
        }else if(file.error() != QFile::NoError){
            std::cerr<<"Error: Cannot read file "
                       <<qPrintable(file_str)<<": "
                         <<qPrintable(file.errorString())<<std::endl;
//            return false;
        }
    }

    if(!isCanRead){
        std::cerr<<"There is no file can read!"<<std::endl;
        return false;
    }

    return true;
}

根据读入的文件路径找到文件并打开文件,将文件内容读入到字符串并加入到QXmlStreamReader中。
注意:由于我读入的xml文件是xml1.1格式,QXmlStreamReader无法解析,所以需要将xml文件的第一行换掉,就如程序中注释的那样。

void XmlReader::readFileTitle(const QString filename)
{
	
    while(!xml.atEnd()){
        if(xml.isStartElement()){
            if(xml.name().toString() == "FaultReport"){
                QTreeWidgetItem* parent = createChildItem();
                parent->setText(0,QObject::tr("FaultReport"));
				parent->setText(1,filename);
                readFirstElement(parent);
            }else{
				qDebug()<<"name = "<<xml.name().toString();
                qDebug()<<"The Name of element is not FaultReport";
                xml.readNext();
            }
        }else{
            xml.readNext();
        }
    }
}
<pre class="cpp" name="code">void XmlReader::readFirstElement(QTreeWidgetItem *parent_item)
{
    xml.readNext();//跳过<FaultReport>

    QTreeWidgetItem* devInfo_item = createChildItem(parent_item);
    devInfo_item->setText(0,QObject::tr("DeviceInfo"));
    QTreeWidgetItem* tripInfo_item = createChildItem(parent_item);
    tripInfo_item->setText(0,QObject::tr("TripInfo"));
    QTreeWidgetItem* digStatus_item = createChildItem(parent_item);
    digStatus_item->setText(0,QObject::tr("DigitalStatus"));
    QTreeWidgetItem* setValue_item = createChildItem(parent_item);
    setValue_item->setText(0,QObject::tr("SettingValue"));
    QTreeWidgetItem* faultInfo_item = createChildItem(parent_item);
    faultInfo_item->setText(0,QObject::tr("FaultInfo"));
    QTreeWidgetItem* dataFileSize_item = createChildItem(parent_item);
    dataFileSize_item->setText(0,QObject::tr("DataFileSize"));
    QTreeWidgetItem* faultKeepingTime_item = createChildItem(parent_item);
    faultKeepingTime_item->setText(0,QObject::tr("FaultKeepingTime"));
    QTreeWidgetItem* FaultStartTime_item = createChildItem(parent_item);
    FaultStartTime_item->setText(0,QObject::tr("FaultStartTime"));

    while(!xml.atEnd()){
        if(xml.isEndElement()){//</FaultReport>
            xml.readNext();
            break;
        }

        if(xml.isStartElement()){
            if(xml.name().toString() == "DeviceInfo"){
                readDeviceInfoElement(devInfo_item);
            }else if(xml.name().toString() == "TripInfo"){
                readTripInfoElement(tripInfo_item);
            }else if(xml.name().toString() == "DigitalStatus"){
                readDigStausElement(digStatus_item);
            }else if(xml.name().toString() == "SettingValue"){
                readSetValElement(setValue_item);
            }else if(xml.name().toString() == "FaultInfo"){
                readFaultInfoElement(faultInfo_item);
            }else if(xml.name().toString() == "DataFileSize"){
                readDataFileSizeElement(dataFileSize_item);
            }else if(xml.name().toString() == "FaultKeepingTime"){
                readFaultKeepingTimeElement(faultKeepingTime_item);
            }else if(xml.name().toString() == "FaultStartTime"){
                readFaultStartTimeElement(FaultStartTime_item);
            }else{
                skipUnknownElement();
            }
        }else{
			xml.readNext();
		}
    }
}

上述两个函数就是对xml进行解析,这里有一个注意点,就是xml.name()返回的是QStringRef,需要转化为QString才能和字符串进行比较。
 
<p>void XmlReader::readDeviceInfoElement(QTreeWidgetItem *parent_item)
{
    QString name_str,val_str;
    xml.readNext();</p><p>    QTreeWidgetItem* devChild = createChildItem(parent_item);</p><p>    while(!xml.atEnd())
    {
        if(xml.isEndElement()){// '/DeviceInfo'
            xml.readNext();
            break;
        }</p><p>        if(xml.isStartElement()){
            if(xml.name().toString() == "name"){
//                xml.readNext();
                name_str = xml.readElementText();</p><p>                devChild->setText(0,name_str);</p><p>                if(xml.isEndElement()){
                    xml.readNext();
                }
            }else if(xml.name().toString() == "value"){
                val_str = xml.readElementText();</p><p>                devChild->setText(1,val_str);</p><p>                if(xml.isEndElement()){
                    xml.readNext();
                }
            }else{
                skipUnknownElement();
            }
        }else{
   xml.readNext();
  }
    }
    qDebug()<<"read one device info";
}</p>
其他几个函数都是类似的编程结构,在此就不一一提供了,最后看一下显示效果吧
<img src="https://img-blog.csdn.net/20141120104239812?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbmV3eWhlcg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值