Qt之解析XML元素(QXmlStreamReader)

简述

对于 XML 的内容,通常情况下,我们只关心 XML 元素的解析。这时,可以通过 QXmlStreamReader 中的便利函数 readNextStartElement() 来实现。

  • 简述
  • 详细介绍
  • 使用
  • 更多参考

详细介绍

之前使用的方式主要使用 readNext() 来读取下一个标记,并返回对应的类型。

QXmlStreamReader xml;
...
while (!xml.atEnd()) {
    xml.readNext();
    ... // 做处理
}
if (xml.hasError()) {
    ... // 做错误处理
}

这对于读取注释、字符、DTD、结束标签等类型比较方便。当只关心 XML 元素的解析,这时,此种方式就显得比较复杂了,下面介绍一种简单方式。

在介绍之前,先明确一个概念:

  • 当前元素:
    当前元素是匹配最近解析的开始元素的元素,其中匹配的结束元素尚未到达。当解析器到达结束元素时,当前元素将成为父元素。

下面,主要用到 QXmlStreamReader 的两个接口:

bool readNextStartElement()

读取,直到当前元素的下一个开始元素。当达到开始元素时,返回 true;当达到结束元素或发生错误时,返回 false。

void skipCurrentElement()

读取,直到当前元素的结尾,跳过任何子节点。此函数对于跳过未知元素非常有用。

使用

为了便于演示,使用上节生成的格式化 XML(Blogs.xml):

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--纯正开源之美,有趣、好玩、靠谱。。。-->
<?xml-stylesheet type="text/css" href="style.css"?>
<!DOCTYPE Blogs [ <!ENTITY Copyright "Copyright 2016《Qt实战一二三》"> <!ELEMENT Blogs (Blog)> <!ELEMENT Blog (作者,主页,个人说明)> <!ELEMENT 作者     (#PCDATA)> <!ELEMENT 主页     (#PCDATA)> <!ELEMENT 个人说明  (#PCDATA)> ]>
<Blogs Version="1.0">
    <Blog>
        <作者>一去丶二三里</作者>
        <主页>http://blog.csdn.net/liang19890820</主页>
        <个人说明>青春不老,奋斗不止!</个人说明>&Copyright;<![CDATA[<Qt分享&&交流>368241647</Qt分享&&交流>]]>&gt;<Empty/>
    </Blog>
</Blogs>

详细说明见:Qt之生成XML(QXmlStreamWriter)

封装一个解析类 XMLReader,XMLReader.h 如下所示:

#ifndef XMLREADER_H
#define XMLREADER_H

#include <QXmlStreamReader>

class XMLReader
{
public:
    XMLReader();
    bool read(QIODevice *device);
    QString errorString() const;  // 错误信息

private:
    void readXBEL();  // 读取根元素 <Blogs>
    void readBlog();  // 读取元素 <Blog>
    void readAuthor();  // 读取元素 <作者>
    void readHOME();   // 读取元素 <主页>
    void readInstruction();  // 读取元素 <个人说明>

    QXmlStreamReader xml;
};

#endif // XMLREADER_H

XMLReader.cpp 如下所示:

#include "XMLReader.h"
#include <QDebug>

#define ROOT_ELEMENT "Blogs"
#define BLOG_ELEMENT "Blog"
#define AUTHOR_ELEMENT QString::fromLocal8Bit("作者")
#define HOME_ELEMENT QString::fromLocal8Bit("主页")
#define INSTRUCTION_ELEMENT QString::fromLocal8Bit("个人说明")
#define VERSION_ATTRIBUTE "Version"

XMLReader::XMLReader()
{

}

bool XMLReader::read(QIODevice *device)
{
    xml.setDevice(device);

    if (xml.readNextStartElement()) {
        QString strName = xml.name().toString();
        if (strName== ROOT_ELEMENT) {  // 获取根元素
            QXmlStreamAttributes attributes = xml.attributes();
            if (attributes.hasAttribute(VERSION_ATTRIBUTE)) {  // 存在属性 Version
                QString strVersion = attributes.value(VERSION_ATTRIBUTE).toString();
                if (strVersion == "1.0") {  // 可以作为版本兼容性判断
                    qDebug() << "Version : " << strVersion;
                    readXBEL();
                } else {
                    xml.raiseError("The file is not an XBEL version 1.0 file.");
                }
            }
        } else {
            xml.raiseError("XML file format error.");
        }
    }

    return !xml.error();
}

// 错误信息
QString XMLReader::errorString() const
{
    return QString("Error:%1  Line:%2  Column:%3")
            .arg(xml.errorString())
            .arg(xml.lineNumber())
            .arg(xml.columnNumber());
}

// 读取根元素 <Blogs>
void XMLReader::readXBEL()
{
    Q_ASSERT(xml.isStartElement() && xml.name().toString() == ROOT_ELEMENT);

    while (xml.readNextStartElement()) {
        if (xml.name().toString() == BLOG_ELEMENT) {
            readBlog();
        } else {
            xml.skipCurrentElement();  // 跳过当前元素
        }
    }
}

// 读取元素 <Blog>
void XMLReader::readBlog()
{
    Q_ASSERT(xml.isStartElement() && xml.name().toString() == BLOG_ELEMENT);

    while (xml.readNextStartElement()) {
        if (xml.name().toString() == AUTHOR_ELEMENT)
            readAuthor();
        else if (xml.name().toString() == HOME_ELEMENT)
            readHOME();
        else if (xml.name().toString() == INSTRUCTION_ELEMENT)
            readInstruction();
        else
            xml.skipCurrentElement();  // 跳过当前元素
    }
}

// 读取元素 <作者>
void XMLReader::readAuthor()
{
    Q_ASSERT(xml.isStartElement() && xml.name().toString() == AUTHOR_ELEMENT);

    QString strAuthor = xml.readElementText();
    qDebug() << QString::fromLocal8Bit("作者:%1").arg(strAuthor);
}

// 读取元素 <主页>
void XMLReader::readHOME()
{
    Q_ASSERT(xml.isStartElement() && xml.name().toString() == HOME_ELEMENT);

    QString strHome = xml.readElementText();
    qDebug() << QString::fromLocal8Bit("主页:%1").arg(strHome);
}

// 读取元素 <个人说明>
void XMLReader::readInstruction()
{
    Q_ASSERT(xml.isStartElement() && xml.name().toString() == INSTRUCTION_ELEMENT);

    QString strInstruction = xml.readElementText();
    qDebug() << QString::fromLocal8Bit("个人说明:%1").arg(strInstruction);
}

使用时,调用 readXML() 即可。

#include <QFile>
#include "XMLReader.h"

// 解析 XML
void readXML() {
    QString strFile("Blogs.xml");
    QFile file(strFile);
    if (!file.open(QFile::ReadOnly | QFile::Text)) {  // 以只读模式打开
        qDebug() << QString("Cannot read file %1(%2).").arg(strFile).arg(file.errorString());
        return;
    }

    XMLReader reader;
    if (!reader.read(&file)) {
        qDebug() << QString("Parse error in file %1(%2).").arg(strFile).arg(reader.errorString());
    }
}

更多参考

时间: 2024-07-28 13:58:39

Qt之解析XML元素(QXmlStreamReader)的相关文章

Qt之解析XML(QXmlStreamReader)

简述 QXmlStreamReader 类提供了一个快速解析器,用于通过简单的流 API 读取格式良好的 XML.与之相对应的是 QXmlStreamWriter(写入 XML). 相比较 Qt 自己的 SAX 解析器(见 QXmlSimpleReader),QXmlStreamReader 更快,更方便.某些情况下,在使用 DOM 树(见 QDomDocument)的应用程序中,它也可能是一个更快,更方便的替代方案. QXmlStreamReader 可以从 QIODevice(见 setDe

PHP解析XML 元素结构范例

该范例用缩进格式显示一个文档中起始元素的结构. 显示 XML 元素结构 <?php$file = "data.xml";$depth = array(); function startElement($parser, $name, $attrs) {   global $depth;   for ($i = 0; $i < $depth[$parser]; $i++) {       print "  ";   }   print "$name

Qt之生成XML(QXmlStreamWriter)

简述 QXmlStreamWriter 类提供了一个使用简单的流 API,用于写入 XML,与之相对应的是 QXmlStreamReader(读取 XML). 正如其相关类,它可以在 setDevice() 指定的 QIODevice 上操作.API 很简单明了:对于想要写的每个 XML 标签或事件,QXmlStreamWriter 都提供了一个专门的函数. 简述 详细介绍 使用 更多参考 详细介绍 元素标签使用 writeStartElement() 打开,紧随其后的是 writeAttrib

Python解析xml中dom元素的方法_python

本文实例讲述了Python解析xml中dom元素的方法.分享给大家供大家参考.具体实现方法如下: 复制代码 代码如下: from xml.dom import minidom try:     xmlfile = open("path.xml", "a+")     #xmldoc = minidom.parse( sys.argv[1])     xmldoc = minidom.parse(xmlfile) except :     #updatelogger.

java-求助SAX解析XML时为什么不加上stack.pop()无法打印出元素文本内容?

问题描述 求助SAX解析XML时为什么不加上stack.pop()无法打印出元素文本内容? package com.shengsiyuan.xml.sax; import java.io.File; import java.util.Stack; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.xml.sax.Attributes; import org.xml.s

xml+dom4j+数据库-初学xml,用dom4j怎么解析xml的混合类型元素?

问题描述 初学xml,用dom4j怎么解析xml的混合类型元素? 我是一个在校学生,刚刚接触xml,通过学习知道怎么用dom4j解析解析简单的xml文件,但是遇到混合元素的话就不太懂,有以下问题希望各位大神帮忙: 1.混合元素中的子元素可以出现多次,如何解析这个出现多次的元素,并把内容存入数据库?如:name的dtd定义和xml文档片段如下,怎么解析两个first,我只能解析出一个: <!ELEMENT name (first+, middle?, last)> <!ELEMENT fi

编码-c# 解析XML并讲每个元素转为类

问题描述 c# 解析XML并讲每个元素转为类 目前公司需要开发一个内部使用的自动化测试框架,老大希望用XML作为前端脚本,后端用c#处理. 前端样式如下: <?xml version="1.0" encoding="ISO-8859-1"?> <a:table xmlns:a="http://www.w3.org/a" xmlns:b="http://www.w3.org/b"> <a:tr>

JS解析XML文件和XML字符串详解

 JS解析XML文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 <script type='text/javascript'> loadXML = function(xmlFile){ var xmlDoc=null; //判断浏览器的类型 //支持IE浏览器 if(!window.DOMParser && windo

python sax模块解析xml遇到非法字符怎么解决?

问题描述 python sax模块解析xml遇到非法字符怎么解决? 1C 用python的sax模块解析xml的时候出现非法字符直接停止了,百度搜到有大神说用回调函数处理当前的非法字符或者跳过直接运行接下来的内容.不过具体应该怎么实现呢?求大神赐教.下面是我的代码,非法字符是出现再其中的很多个tagname=""url""中的内容,能在原来的基础上改就更好了,再次感谢 import xml.saxclass XmlHandler( xml.sax.ContentHa