一、描述
QXmlStreamReader 提供了一个简单的流 API 来解析格式良好的 XML。
QXmlStreamReader 的典型用法如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<data info="this is data infomation" editor="张三">
<website herf="www.baidu.com">
<title>
<name>baidu</name>
</title>
</website>
<website herf="www.sohu.com">
<title>
<name>sohu</name>
</title>
</website>
</data>
int main(int argc, char *argv[])
{
QFile file("demo.xml");
if (!file.open(QIODevice::ReadOnly))
return 0;
QXmlStreamReader reader(&file);
while(!reader.atEnd())
{
if(reader.isStartElement())
{
foreach (const QXmlStreamAttribute & attribute, reader.attributes())
{
qDebug()<<attribute.name();
qDebug()<<attribute.value();
qDebug()<<endl;
}
}
reader.readNext();
}
if (reader.hasError())
{
qDebug()<<reader.errorString();
}
file.close();
}
QXmlStreamReader 在设计上是内存保守的,因为它不会将整个 XML 文档树存储在内存中,而是仅存储当前标记。 此外,它通过将所有字符串数据报告为 QStringRef 而不是真正的 QString 对象来实现这一点。
二、类型成员
1、enum QXmlStreamReader::Error
- NoError:无错误。
- CustomError:使用 raiseError() 引发了自定义错误。
- NotWellFormedError:由于读取的 XML 格式不正确,解析器在内部引发了错误。
- PrematureEndOfDocumentError:输入流在格式正确的 XML 文档被解析之前结束。
- UnexpectedElementError:解析器遇到了与预期不同的元素。
2、enum QXmlStreamReader::ReadElementTextBehaviour:此枚举指定了 readElementText() 的行为。
- ErrorOnUnexpectedElement:引发 UnexpectedElementError 并返回当前遇到子元素时读取的内容。
- IncludeChildElements:递归地包含子元素中的文本。
- SkipChildElements:跳过子元素。
3、enum QXmlStreamReader::TokenType:此枚举指定读取器当前读取的类型。
- NoToken:还没有读到任何东西。
- Invalid:发生了错误,在 error() 和 errorString() 中报告。
- StartDocument:在 documentVersion() 中报告 XML 版本号,在 documentEncoding() 中报告 XML 文档中指定的编码。如果文档被声明为独立的,则 isStandaloneDocument() 返回 true。
- EndDocument:报告文档的结尾。
- StartElement:使用 namespaceUri() 和 name() 报告元素的开始。 空元素也报告为 StartElement,后跟 EndElement。 属性在 attributes() 中报告,命名空间声明在 namespaceDeclarations() 中。
- EndElement:使用 namespaceUri() 和 name() 报告元素的结尾。
- Characters:在 text() 中报告字符。 如果字符都是空白字符,则 isWhitespace() 返回 true。如果字符来自 CDATA 部分,则 isCDATA() 返回 true。
- Comment:在 text() 中报告注释。
- DTD:在 text() 中报告 DTD,在 notationDeclarations() 中报告符号声明,在 entityDeclarations() 中报告实体声明。DTD 声明的详细信息在 dtdName()、dtdPublicId() 和 dtdSystemId() 中报告。
- EntityReference:报告无法解析的实体引用。引用的名称在 name() 中报告,替换文本在 text() 中。
- ProcessingInstruction:在 processingInstructionTarget() 和 processingInstructionData() 中报告处理指令。
三、属性成员
1、namespaceProcessing : bool:此属性控制流读取器是否处理命名空间。如果启用,读取器处理命名空间,否则不处理。默认情况下,名称空间处理处于启用状态。
四、成员函数
1、QXmlStreamReader(QIODevice *device)
构造函数。
2、void addData(const QByteArray &data)
void addData(const QString &data)
void addData(const char *data)
添加更多数据供解析器解析。如果已经设置了设备(setDevice(QIODevice *device)),则不执行任何操作。
QString xmlData = R"(<?xml version="1.0" encoding="UTF-8"?>
<data info="this is data infomation" editor="张三">
<website herf="www.baidu.com">
<title>
<name>baidu</name>
</title>
</website>
</data>)";
QXmlStreamReader reader;
reader.addData(xmlData);
while(!reader.atEnd())
{
if(reader.isStartElement())
{
foreach (const QXmlStreamAttribute & attribute, reader.attributes())
{
qDebug()<<attribute.name();
qDebug()<<attribute.value();
qDebug()<<endl;
}
}
reader.readNext();
}
if (reader.hasError())
{
qDebug()<<reader.errorString();
}
3、bool atEnd()
如果读取器一直读取到 XML 文档的结尾,或者发生了 error() 并且读取已中止,则返回 true。 否则,它返回 false。(一旦有更多数据可用,atEnd() 将返回 false)
当atEnd() 和hasError() 返回true 并且error() 返回PrematureEndOfDocumentError 时,表示到目前为止XML 已经格式良好,但还没有解析完整的XML 文档。
4、QXmlStreamAttributes attributes()
返回 StartElement 的属性。
5、qint64 characterOffset()
qint64 columnNumber() / qint64 lineNumber()
返回当前字符偏移量,从 0 开始。
返回当前列号,从 0 开始。 / 返回当前行号,从 1 开始。
6、void clear()
从读取器中删除任何device()或数据,并将其内部状态重置为初始状态。
7、QStringRef documentEncoding()
如果 tokenType() 为 StartDocument,则此函数返回 XML 声明中指定的编码字符串。否则返回空字符串。
8、QStringRef documentVersion()
如果 tokenType() 为 StartDocument,则此函数返回 XML 声明中指定的版本字符串。否则返回空字符串。
9、QStringRef dtdName()
QStringRef dtdPublicId()
QStringRef dtdSystemId()
输出DTD信息。
10、bool hasError()
是否发生错误。
11、QStringRef name()
返回 StartElement、EndElement、EntityReference 的本地名称。
while(!reader.atEnd())
{
if(reader.isStartElement())
{
qDebug()<<"isStartElement name"<<reader.name();
}
if(reader.isEndElement())
{
qDebug()<<"isEndElement name"<<reader.name();
}
reader.readNext();
}
12、QStringRef processingInstructionData() / QStringRef processingInstructionTarget()
处理指令信息。
while(!reader.atEnd())
{
if(reader.isProcessingInstruction())
{
qDebug()<<"processingInstructionData:"<<reader.processingInstructionData();
qDebug()<<"processingInstructionTarget:"<<reader.processingInstructionTarget();
}
reader.readNext();
}
13、void raiseError(const QString &message = QString())
使用可选的错误消息引发自定义错误。
int sum{0};
while(!reader.atEnd())
{
if(reader.isStartElement())
{
++sum;
reader.raiseError(reader.name() + "没有错误");
if (reader.hasError())
{
qDebug()<<reader.errorString();
}
}
reader.readNext();
}
qDebug()<<"sum = "<<sum;
引发错误后解析就停止了。
14、QString readElementText(QXmlStreamReader::ReadElementTextBehaviour behaviour = ErrorOnUnexpectedElement)
读取 StartElement 时调用的便利函数。读取直到对应的 EndElement 并返回其间的所有文本。在没有错误的情况下,调用此函数后的当前标记(tokenType())是 EndElement。
如果当前标记不是 StartElement,则返回空字符串。
while(!reader.atEnd())
{
if(reader.isStartElement())
{
qDebug()<<reader.readElementText();
}
reader.readNext();
}
15、QXmlStreamReader::TokenType readNext()
读取下一个标记并返回其类型。除了一个例外,一旦 readNext() 报告了 error(),就无法进一步读取 XML 流。 然后atEnd()返回true,hasError()返回true,此函数返回QXmlStreamReader::Invalid。
例外情况是 error() 返回 PrematureEndOfDocumentError。当到达其他格式良好的 XML 块的末尾时会报告此错误类型,但该块不代表完整的 XML 文档。在这种情况下,当从 QByteArray 读取流时,可以通过调用 addData() 添加下一个 XML 块来恢复解析,或者在从 device() 读取流时等待更多数据到达。
16、bool readNextStartElement()
读取直到当前元素中的下一个开始元素。到达开始元素时返回 true。当到达结束元素或发生错误时,返回 false。
当前元素是与最近解析的起始元素匹配的元素,但尚未到达其匹配的结束元素。当解析器到达结束元素时,当前元素成为父元素。
当只关心解析 XML 元素时,这是一个便捷的函数。
while(reader.readNextStartElement())
{
if(reader.isStartElement())
{
foreach (const QXmlStreamAttribute & attribute, reader.attributes())
{
qDebug()<<attribute.name();
qDebug()<<attribute.value();
qDebug()<<endl;
}
}
reader.readNext();
}
17、void setDevice(QIODevice *device)
设置设备。设置设备会将读取器重置为其初始状态。
18、void setEntityExpansionLimit(int limit)
设置单个实体允许扩展到的最大字符数限制。 如果单个实体扩展到超过给定的限制,则文档不被视为格式良好。此属性的默认值为 4096 个字符。
该限制是为了在加载未知 XML 文档时防止 DoS 攻击,否则递归实体扩展可能会耗尽所有可用内存。
19、void skipCurrentElement()
读取到当前元素的结尾,跳过任何子节点。此功能对于跳过未知元素很有用。