(四) - 分析 QXmlStream.h 文件框架 - TokenType - QXmlStreamReader
STEP1、QT源码闭源,只开放.h接口供调用
以 - xml/ # XML相关实现(QXmlStreamReader等) 来做分析。
STEP2、QXmlStream 模块中的类归纳 - 九大类 , 当前只关注 QXmlStreamReader 和 QXmlStreamAttribute
Q_CORE_EXPORT QXmlStreamStringRef
Q_CORE_EXPORT QXmlStreamAttribute
Q_CORE_EXPORT QXmlStreamAttributes : public QVector<QXmlStreamAttribute>
Q_CORE_EXPORT QXmlStreamNamespaceDeclaration
Q_CORE_EXPORT QXmlStreamNotationDeclaration
Q_CORE_EXPORT QXmlStreamEntityDeclaration
Q_CORE_EXPORT QXmlStreamEntityResolver
Q_CORE_EXPORT QXmlStreamReader
Q_CORE_EXPORT QXmlStreamWrite

STEP3、QXmlStreamReader 的应用场景 : 读取 配置文件 举例子说明
此函数从给定的 QIODevice 读取 XML 数据,查找所有的 <interface> 元素,并提取它们的 name 属性和内容(IP 地址)
void parseNetworkConfig(QIODevice *device) {
QXmlStreamReader reader(device);
while (!reader.atEnd()) {
if (reader.readNextStartElement()) { // 移动到下一个开始元素(如果有)
if (reader.name() == "interface") {
QString name = reader.attributes().value("name").toString();
QString ip = reader.readElementText();
qDebug() << "Interface:" << name << "IP:" << ip;
}
}
}
}
<config>
<interface name="eth0">192.168.1.1</interface>
<interface name="wlan0">192.168.1.100</interface>
</config>
STEP4、分析 QXmlStreamReader 类
#ifndef QT_NO_XMLSTREAMREADER
class Q_CORE_EXPORT QXmlStreamReader {
QDOC_PROPERTY(bool namespaceProcessing READ namespaceProcessing WRITE setNamespaceProcessing)
public:
enum TokenType {
NoToken = 0,
Invalid,
StartDocument,
EndDocument,
StartElement,
EndElement,
Characters,
Comment,
DTD,
EntityReference,
ProcessingInstruction
};
// 数据输入与初始化 : 多源支持:通过构造函数或 setDevice() 支持从 QIODevice、QByteArray、QString 等读取数据
QXmlStreamReader();
explicit QXmlStreamReader(QIODevice *device);
explicit QXmlStreamReader(const QByteArray &data);
explicit QXmlStreamReader(const QString &data);
explicit QXmlStreamReader(const char * data);
~QXmlStreamReader();
// 增量解析:addData() 方法允许动态追加数据,适用于网络流或实时数据
void setDevice(QIODevice *device);
QIODevice *device() const;
void addData(const QByteArray &data);
void addData(const QString &data);
void addData(const char *data);
void clear();
// 状态查询
bool atEnd() const; // 判断是否到达文档末尾
TokenType tokenType() const; // 返回当前解析位置的标记类型
QString tokenString() const; // 返回当前标记的文本内容
// 事件驱动
TokenType readNext(); // 移动到下一个标记并返回其类型 , readNext 是方法名,而不是枚举值, 返回类型:TokenType 枚举
bool readNextStartElement(); // 跳过无关标记,直到遇到下一个开始标签
void skipCurrentElement(); // 跳过当前元素的全部内容(包括子元素)
void setNamespaceProcessing(bool);
bool namespaceProcessing() const;
// 这些内联函数用于判断当前解析位置的标记类型,分别对应文档开始、文档结束、元素开始、元素结束和文本内容。
// 基本类型判断函数
inline bool isStartDocument() const { return tokenType() == StartDocument; }
inline bool isEndDocument() const { return tokenType() == EndDocument; }
inline bool isStartElement() const { return tokenType() == StartElement; }
inline bool isEndElement() const { return tokenType() == EndElement; }
inline bool isCharacters() const { return tokenType() == Characters; }
// 特殊类型判断函数
bool isWhitespace() const;
bool isCDATA() const;
inline bool isComment() const { return tokenType() == Comment; }
inline bool isDTD() const { return tokenType() == DTD; }
inline bool isEntityReference() const { return tokenType() == EntityReference; }
inline bool isProcessingInstruction() const { return tokenType() == ProcessingInstruction; }
bool isStandaloneDocument() const;
QStringRef documentVersion() const;
QStringRef documentEncoding() const;
qint64 lineNumber() const;
qint64 columnNumber() const;
qint64 characterOffset() const;
QXmlStreamAttributes attributes() const;
enum ReadElementTextBehaviour {
ErrorOnUnexpectedElement,
IncludeChildElements,
SkipChildElements
};
QString readElementText(ReadElementTextBehaviour behaviour = ErrorOnUnexpectedElement);
QStringRef name() const;
QStringRef namespaceUri() const;
QStringRef qualifiedName() const;
QStringRef prefix() const;
QStringRef processingInstructionTarget() const;
QStringRef processingInstructionData() const;
QStringRef text() const;
QXmlStreamNamespaceDeclarations namespaceDeclarations() const;
void addExtraNamespaceDeclaration(const QXmlStreamNamespaceDeclaration &extraNamespaceDeclaraction);
void addExtraNamespaceDeclarations(const QXmlStreamNamespaceDeclarations &extraNamespaceDeclaractions);
QXmlStreamNotationDeclarations notationDeclarations() const;
QXmlStreamEntityDeclarations entityDeclarations() const;
QStringRef dtdName() const;
QStringRef dtdPublicId() const;
QStringRef dtdSystemId() const;
enum Error {
NoError,
UnexpectedElementError,
CustomError,
NotWellFormedError,
PrematureEndOfDocumentError
};
void raiseError(const QString& message = QString());
QString errorString() const;
Error error() const;
inline bool hasError() const
{
return error() != NoError;
}
void setEntityResolver(QXmlStreamEntityResolver *resolver);
QXmlStreamEntityResolver *entityResolver() const;
private:
Q_DISABLE_COPY(QXmlStreamReader)
Q_DECLARE_PRIVATE(QXmlStreamReader)
QScopedPointer<QXmlStreamReaderPrivate> d_ptr;
};
#endif // QT_NO_XMLSTREAMREADER
4.1 TokenType 枚举解析:XML 文档的事件类型系统

4.1.1 枚举的核心作用 ( 1. 事件驱动解析的基础 & 2. 节点类型快速判断 & 3. 错误检测与恢复)
流式解析器通过识别不同 TokenType 来驱动处理逻辑,例如:
while (reader.readNext()) {
switch (reader.tokenType()) {
case QXmlStreamReader::StartElement:
processStartElement();
break;
case QXmlStreamReader::Characters:
processTextContent();
break;
// 其他类型处理...
}
}
提供便捷的类型检查接口:
if (reader.isStartElement()) { // 等价于 tokenType() == StartElement
// 处理开始元素
}
if (reader.isComment()) { // 等价于 tokenType() == Comment
// 处理注释
}
错误检测与恢复
待补充
4.1.2 TokenType - 典型应用场景
1. 元素结构识别
// 解析如下 XML: <library>
<book id="b001">
<title>Effective C++</title>
<author>Scott Meyers</author>
</book>
</library> if (reader.tokenType() == StartElement && reader.name() == "book") { // 此时解析器位于 <book id="b001">标签,处理book元素属性 QString id = reader.attributes().value("id").toString(); // id = "b001" while (reader.readNext()) {
// 第一次循环 : 定位到 <title> 元素 if (reader.tokenType() == StartElement && reader.name() == "title") {
// 此时解析器位于< title > 标签 reader.readNext(); // 移动到Characters,即标签内的文本节点 if (reader.tokenType() == Characters) { QString title = reader.text().toString(); // title = "Effective C++" } } else if (reader.tokenType() == EndElement && reader.name() == "book") { break; // 结束book元素处理 } } }

2. 文本内容与注释区分
if (reader.tokenType() == Characters) {
if (!reader.isWhitespace()) { // 过滤空白字符
processRealText(reader.text());
}
} else if (reader.tokenType() == Comment) {
qDebug() << "注释内容:" << reader.text().toString();
}
3. DTD 与处理指令解析 - 不研究
if (reader.tokenType() == Invalid) {
qDebug() << "解析错误位于第" << reader.lineNumber()
<< "行,第" << reader.columnNumber() << "列";
}
4.1.3
4.1.4
4.1.5
4.1.6
4.2
4.3
4.4
STEP5、
STEP6、
STEP7、
STEP8、
STEP9、
STEP10、
STEP
浙公网安备 33010602011771号