Qt模块化笔记之core——QXmlStreamReader的使用

本文介绍Qt中的QXmlStreamReader类的基本用法,包括构造函数、成员函数等,并通过一个实例展示了如何解析XML文件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

QXmlStreamReader

公有函数如下:

	QXmlStreamReader()
	QXmlStreamReader(QIODevice * device)
	QXmlStreamReader(const QByteArray & data)
	QXmlStreamReader(const QString & data)
	QXmlStreamReader(const char * data)
	~QXmlStreamReader()

void	setDevice(QIODevice * device)//以下四个都用于添加xml数据
void	addData(const QByteArray & data)
void	addData(const QString & data)
void	addData(const char * data)

void	addExtraNamespaceDeclaration(const QXmlStreamNamespaceDeclaration & extraNamespaceDeclaration)//添加额外命名空间申明
void	addExtraNamespaceDeclarations(const QXmlStreamNamespaceDeclarations & extraNamespaceDeclarations)
void	setEntityResolver(QXmlStreamEntityResolver * resolver)//添加实体解析器
void	setNamespaceProcessing(bool)

bool	atEnd() const//以下几个用于循环中,遍历元素(标签)
TokenType	readNext()
QString	readElementText(ReadElementTextBehaviour behaviour = ErrorOnUnexpectedElement)
bool	readNextStartElement()
void	skipCurrentElement()//跳过当前元素
void	clear()

bool	isDTD() const//以下判断当前遍历到的元素属于哪种类型
bool	isCDATA() const
bool	isCharacters() const
bool	isComment() const
bool	isStartDocument()const
bool	isStartElement() const
bool	isEndDocument() const
bool	isEndElement() const
bool	isEntityReference() const
bool	isProcessingInstruction() const
bool	isStandaloneDocument() const
bool	isWhitespace() const

QStringRef	documentEncoding() const
QStringRef	documentVersion() const
QStringRef	dtdName() const
QStringRef	dtdPublicId() const
QStringRef	dtdSystemId() const
qint64	lineNumber() const
QStringRef	name() const//仅返回StartElement, EndElement或EntityReference的标签名
QStringRef	prefix() const//返回的应是涉及命名空间的前辍
QStringRef	text() const//仅返回Characters, Comment, DTD, 或 EntityReference.中的文本部分
QString	tokenString() const
TokenType	tokenType() const
QIODevice *	device() const
qint64	characterOffset() const
qint64	columnNumber() const//返回当前解析到的行数

bool	hasError() const//出错处理
Error	error() const
QString	errorString() const
void	raiseError(const QString & message = QString())

QXmlStreamAttributes	attributes() const
QXmlStreamEntityDeclarations	entityDeclarations() const
QXmlStreamEntityResolver *	entityResolver() const
QXmlStreamNamespaceDeclarations	namespaceDeclarations() const
QStringRef	processingInstructionData() const
QStringRef	processingInstructionTarget() const
QStringRef	qualifiedName() const
bool	namespaceProcessing() const
QStringRef	namespaceUri() const
QXmlStreamNotationDeclarations	notationDeclarations() const
将上节的某篇抄过来,并添加一些部分,说明各部分与Qt对应的函数名:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>  
<!--这是一个便签-->  
<!DOCTYPE Notes [  
    <!ELEMENT note (date,message)>  
    <!ELEMENT date (#PCDATA)>  
    <!ELEMENT message (#PCDATA)>  
]>  
<Notes>  
    <note>  
        <date>2月1日</date>  
        <message>别忘了参加party</message>  
    </note>  
    <note> 
	<?this is the most important ?> 
        <date>2月14日</date>  
        <message>今天情人节啊</message>  
    </note>  
    <note>  
        <date>2月18日</date>  
        <message>今天自己煮饭吧</message>  
    </note>  
</Notes>

左边的为qt中的函数名,右端为对应XML部分

头部声明部分

StartDocument()——<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

documentVersion()——version="1.0"

documentEncoding()——encoding="UTF-8"

StandaloneDocument()——standalone="yes"

DTD部分

notationDeclarations()——<!ELEMENT note (date,message)>

entityDeclarations()——<!ELEMENT date (#PCDATA)><!ELEMENT message (#PCDATA)>

dtdName——Notes,<!DOCTYPE 后的那个,也即根元素名

dtdPublicId()和dtdSystemId()——注来自点此查看区别

实体部分:

CDATA()——CDATA 部分中的所有内容都会被解析器忽略而直接有效,与注释不同,格式为:<![CDATA[" 内容 "]]>。见点击打开链接

EntityReference——实体引用


ProcessingInstruction()——处理指令,看下面的引用说明

引自:

http://zhidao.baidu.com/question/67891842.html?si=1

下面的一行就是在第二本书的定义之前的:
<?page render multiple authors ?>
虽然它看上去很像XML序言,但实际上是一种称为处理指令(processing instruction)的不同类型的语法。处理指令(以下简称PI)的目的是为了给处理页面的程序(例如XML解析器)提供额外的信息。PI通常情况下是没有固定格式的,唯一的要求是紧随第一个问号必须至少有一个字母。在此之后,PI可以包含除了小于号和大于号之外的任何字符串序列。最常见的PI是用来指定XML文件的样式表:这个PI一般会直接放在XML序言之后,通常由Web浏览器使用,来将XML数据以特殊的样式显示出来。


 这个类自身有个TokenType(标签类型)用来描述当前解析到的文档部分,与上面我归纳的是近似的

enum QXmlStreamReader::TokenType

Constant Value Description
QXmlStreamReader::NoToken 0 The reader has not yet read anything.
QXmlStreamReader::Invalid 1 An error has occurred, reported in error() and errorString().
QXmlStreamReader::StartDocument 2 The reader reports the XML version number indocumentVersion(), and the encoding as specified in the XML document in documentEncoding(). If the document is declared standalone, isStandaloneDocument() returns true; otherwise it returns false.
QXmlStreamReader::EndDocument 3 The reader reports the end of the document.
QXmlStreamReader::StartElement 4 The reader reports the start of an element with namespaceUri() and name(). Empty elements are also reported as StartElement, followed directly by EndElement. The convenience functionreadElementText() can be called to concatenate all content until the corresponding EndElement. Attributes are reported inattributes(), namespace declarations innamespaceDeclarations().
QXmlStreamReader::EndElement 5 The reader reports the end of an element with namespaceUri() and name().
QXmlStreamReader::Characters 6 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.
QXmlStreamReader::Comment 7 The reader reports a comment in text().
QXmlStreamReader::DTD 8 The reader reports a DTD in text(), notation declarations innotationDeclarations(), and entity declarations inentityDeclarations(). Details of the DTD declaration are reported in in dtdName(), dtdPublicId(), and dtdSystemId().
QXmlStreamReader::EntityReference 9 The reader reports an entity reference that could not be resolved. The name of the reference is reported in name(), the replacement text in text().
QXmlStreamReader::ProcessingInstruction 10 The reader reports a processing instruction inprocessingInstructionTarget() and processingInstructionData().
————————————————————————————————————————————————————————————————————

基础使用示例:


将上面XML代码保存为text.xml。

代码:

#include "dialog.h"
#include "ui_dialog.h"
#include <QFile>
#include <QIODevice>
#include <QDebug>
Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    QFile *file=new QFile("://test.xml");
    if(!file->open(QIODevice::ReadOnly))
    {
        qDebug()<<"文件打开失败";
        return;
    }
    xmlReader =new QXmlStreamReader(file);
    while(!xmlReader->atEnd() && !xmlReader->hasError())
    {
        xmlReader->readNext();
        if(xmlReader->isStartElement())
        {

            if(xmlReader->name()=="note")
            {
                qDebug()<<"————note————";
            }else if (xmlReader->name()=="date") {
                qDebug()<<"date:"<<xmlReader->readElementText();
            }else if (xmlReader->name()=="message") {
                qDebug()<<"message:"<<xmlReader->readElementText();
            }
        }

    }
}

Dialog::~Dialog()
{
    delete ui;
}


输出为:

————note————

date: "2月1日"

message: "别忘了参加party"

————note————

date: "2月14日"

message: "今天情人节啊"

————note————

date: "2月18日"

message: "今天自己煮饭吧" 

————————————————————————————————————————————————————————————————————

对于出错,错语类型枚举值有

enum QXmlStreamReader::Error

Constant Value Description
QXmlStreamReader::NoError 0 无错误
QXmlStreamReader::CustomError 2 自定义错误,通过raiseError()定义错误信息,不懂怎样使用,求赐教
QXmlStreamReader::NotWellFormedError 3 xml格式有问题,比如标签不配对,嵌套不正确。The parser internally raised an error due to the read XML not being well-formed.
QXmlStreamReader::PrematureEndOfDocumentError 4 来源的数据不完整,如通过网络传输来的The input stream ended before a well-formed XML document was parsed. Recovery from this error is possible if more XML arrives in the stream, either by calling addData() or by waiting for it to arrive on thedevice().
QXmlStreamReader::UnexpectedElementError 1 意料之外的元素?求教The parser encountered an element that was different to those it expected.


<think>我们正在使用QtQXmlStreamReader来读取松散格式的HTML文件。由于HTML可能不是严格的XML(例如,标签可能没有正确关闭,或者有自闭合标签等),我们需要谨慎处理。解决方案:使用QXmlStreamReader的纠错能力,并注意处理可能的错误。步骤:1.打开HTML文件,并设置为只读模式。2.创建QXmlStreamReader对象,并将文件内容设置给它。3.通过循环读取器的事件,并根据不同的事件类型处理数据。4.对于松散格式的HTML,我们可能会遇到错误,但QXmlStreamReader会尝试恢复。我们可以忽略一些错误,或者根据错误类型进行特殊处理。注意:QXmlStreamReader对HTML的支持有限,特别是对于非良构的HTML。如果遇到严重的格式问题,可能需要使用专门的HTML解析器(如QtWebEngine模块中的解析器),但这里我们只使用QXmlStreamReader。示例代码:我们将读取HTML文件,并提取所有的文本内容(忽略标签)。但是,请注意:如果HTML非常松散,这种方法可能不理想。但对于简单的HTML文件,可以工作。代码示例: ```cpp#include <QCoreApplication>#include <QFile> #include<QXmlStreamReader>#include <QDebug> intmain(intargc,char *argv[]){QCoreApplication a(argc, argv);QFilefile("test.html");if(!file.open(QIODevice::ReadOnly |QIODevice::Text)){qDebug() <<"无法打开文件";return -1;}QXmlStreamReader reader(&file);QString resultText;//用于保存提取的文本while(!reader.atEnd()) {QXmlStreamReader::TokenTypetype= reader.readNext();if (type ==QXmlStreamReader::StartElement){//可以处理特定元素//例如,如果只想提取段落,可以检查元素名是否为"p"//这里我们提取所有元素的文本}else if(type== QXmlStreamReader::Characters){//提取文本resultText+= reader.text();}}if(reader.hasError()) {//处理错误qDebug()<< "XML解析错误:"<< reader.errorString();//但可能仍然有一些文本被提取}file.close();qDebug()<< "提取的文本内容:" <<resultText;return0;} ```上述代码会提取HTML文件中的所有文本(标签之间的文本)。但是,如果HTML标签属性中有文本,则不会被提取。对于松散HTML,可能出现的错误包括:标签未正确关闭等。QXmlStreamReader在遇到错误时会停止解析,但上述代码中我们只是记录了错误,并继续使用已经读取到的文本。如果需要更健壮的解析,可以考虑使用其他库,如QTextDocument(通过setHtml方法)或者使用Qt WebEngine模块中的HTML解析器。但QXmlStreamReader是一个轻量级的解决方案。引用说明:上述方法参考了QtQXmlStreamReader的基本用法[^1]。 §§相关问题§§1.如何处理HTML文件中的自闭合标签(如`<br/>`)? 2.如何只提取特定标签(如段落`<p>`)内的文本? 3.如果HTML文件格式错误严重,除了QXmlStreamReaderQt还有哪些替代方案可以解析?</think>### 使用 QXmlStreamReader 读取松散 HTML 文件的方法 在 Qt使用 `QXmlStreamReader` 解析松散格式的 HTML 文件时,需要注意 HTML 可能不符合严格的 XML 规范(如未闭合标签、属性引号缺失等)。以下是完整解决方案: #### 核心方法 ```cpp #include <QXmlStreamReader> #include <QFile> #include <QDebug> void parseLooseHTML(const QString& filePath) { QFile file(filePath); if (!file.open(QIODevice::ReadOnly | QTextStream::ReadOnly)) { qWarning() << "文件打开失败"; return; } QXmlStreamReader reader(&file); reader.setNamespaceProcessing(false); // 禁用命名空间处理 while (!reader.atEnd()) { switch (reader.readNext()) { case QXmlStreamReader::StartElement: qDebug() << "开始标签:" << reader.name(); // 读取属性 for (const auto& attr : reader.attributes()) { qDebug() << " |- 属性:" << attr.name() << "=" << attr.value(); } break; case QXmlStreamReader::Characters: if (!reader.isWhitespace()) { qDebug() << "文本内容:" << reader.text().trimmed(); } break; case QXmlStreamReader::EndElement: qDebug() << "结束标签:" << reader.name(); break; case QXmlStreamReader::Invalid: // 处理松散格式错误 if (reader.error() == QXmlStreamReader::NotWellFormedError) { qWarning() << "格式错误,尝试恢复:" << reader.errorString(); reader.clearError(); // 清除错误继续解析 } break; } } if (reader.hasError()) { qCritical() << "解析终止错误:" << reader.errorString(); } file.close(); } ``` #### 关键处理技巧 1. **错误恢复机制** 当遇到 `NotWellFormedError` 错误时(常见于松散 HTML),调用 `clearError()` 清除错误状态并继续解析: ```cpp case QXmlStreamReader::Invalid: if (reader.error() == QXmlStreamReader::NotWellFormedError) { reader.clearError(); // 关键恢复步骤 } ``` 2. **预处理 HTML(推荐)** 使用 Qt 内置工具先清理 HTML: ```cpp #include <QTextDocument> QString sanitizeHTML(const QString& rawHtml) { QTextDocument doc; doc.setHtml(rawHtml); // 自动修正格式 return doc.toHtml(); // 返回规范化的HTML } ``` 3. **标签处理注意事项** - 对于自闭合标签(如 `<br>`),HTML 中可能写作 `<br>` 而非 `<br/>` - 属性值引号可能缺失(如 `<div id=main>`) - 使用 `reader.name().toString()` 获取标签名时忽略大小写差异 #### 使用示例 ```cpp // 在main函数中调用 int main() { parseLooseHTML("index.html"); return 0; } ``` #### 输出示例 ``` 开始标签: "html" 开始标签: "body" 开始标签: "div" |- 属性: "class" = "content" 文本内容: "Hello World" 结束标签: "div" 结束标签: "body" 结束标签: "html" ``` #### 备选方案 对于极端松散的 HTML,建议: 1. 使用 `QTextDocument::setHtml()` 自动修正格式 2. 采用第三方库如 [Gumbo Parser](https://github.com/google/gumbo-parser) 3. 使用 Qt WebEngine 的 `QWebEnginePage::toHtml()`[^1] [^1]: 实现绘制方法:重写paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)方法,以自定义项的绘制方式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值