QXmlStreamReader 解析指南

QXmlStreamReader 解析指南

1.分级负责制

不要在一个循环里处理所有层级的节点。最稳健的架构是“父节点驱动步进,子节点闭环消耗”。

  • 第一层(主循环): 负责使用 readNextStartElement() 寻找业务大块(如 ROI 节点)。

  • 第二层(业务分发): 识别是大块 A 还是大块 B,调用相应的解析函数。

  • 第三层(具体解析): 先读属性,再用内部 while 循环处理嵌套子节点,并确保离开时游标已对齐。

2.关键 API 的规则

在处理 XML 流解析时,理解游标(Cursor)的移动逻辑是避免死循环和跳节点的关键。

API 方法 游标行为 (Cursor Behavior) 典型用途 (Use Case)
attributes() 原地不动。仅读取当前标签头部的属性列表。 在进入 while 循环解析子节点前,获取父标签自带的配置参数
readNextStartElement() 主动步进。自动跳过换行符、空白字符和注释,停在下一个 <StartElement>。若遇到当前层级的 </EndElement> 则返回 false。 驱动循环的核心引擎。能自动处理 XML 复杂的缩进格式,确保逻辑始终指向下一个有效标签。
skipCurrentElement() 快速对齐。将游标从当前 StartElement 直接移向匹配的 EndElement 之后。 处理完某个子节点后,确保游标跳出该节点内部,为主循环读取下一个兄弟节点做准备。
name() 仅读取。获取当前游标所在标签的名称。 用于 if/else 或 switch 分支判断,确定当前走哪条业务逻辑。
isStartElement() 仅读取。判断当前游标是否指向一个开始标签。 常用于进入解析函数时的安全检查。

3. 嵌套节点解析模板(万能公式)

当你遇到一个既带属性又有子节点的元素时,请直接套用此结构:

// [进入函数时] 游标位于 <ParentNode ...>
if (xmlReader.isStartElement() && xmlReader.name() == "ParentNode") 
{
    // 1. 获取当前节点属性(此时游标并未移动)
    auto attrs = xmlReader.attributes();
    int val = attrs.value("attr").toInt();

    // 2. 遍历子节点(readNextStartElement 会把游标推入 ParentNode 内部)
    while (xmlReader.readNextStartElement()) 
    {
        // 直接获取到<StartElement>
        QString subName = xmlReader.name().toString();

        if (subName == "SubNode") {
            // 解析子节点...
            xmlReader.skipCurrentElement(); // [关键] 处理完后跳出子节点
        } 
        else {
            xmlReader.skipCurrentElement(); // [关键] 容错,跳过不认识的子项
        }
    }
    // [退出函数时] while 循环因撞上 </ParentNode> 而停止,游标停在结束标签上
}
posted @ 2026-01-15 21:46  一楼二栋  阅读(2)  评论(0)    收藏  举报