Qt - XML解析与构建

在 Qt 中解析和构建 XML 可以通过 QDomDocument(DOM 模型)或 QXmlStreamReader/QXmlStreamWriter(流式模型)实现。以下是两种方法的详细示例:


一、使用 QDomDocument(DOM 模型)

适合小规模 XML 文件,允许随机访问和修改 XML 节点。

1. 解析 XML 文件

#include <QFile>
#include <QDomDocument>
#include <QDebug>

void parseXmlWithDOM(const QString& filePath) {
    QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qDebug() << "Failed to open file";
        return;
    }

    QDomDocument doc;
    if (!doc.setContent(&file)) {
        qDebug() << "Failed to parse XML";
        file.close();
        return;
    }
    file.close();

    // 获取根节点
    QDomElement root = doc.documentElement();
    qDebug() << "Root element:" << root.tagName();

    // 遍历子节点
    QDomNode node = root.firstChild();
    while (!node.isNull()) {
        if (node.isElement()) {
            QDomElement element = node.toElement();
            qDebug() << "Element:" << element.tagName();

            // 获取属性
            QString attr = element.attribute("attributeName");
            if (!attr.isEmpty()) {
                qDebug() << "Attribute value:" << attr;
            }

            // 获取文本内容
            QDomNode textNode = element.firstChild();
            if (textNode.isText()) {
                qDebug() << "Text:" << textNode.toText().data();
            }
        }
        node = node.nextSibling();
    }
}

2. 构建 XML 文件

#include <QFile>
#include <QDomDocument>
#include <QDebug>

void buildXmlWithDOM(const QString& filePath) {
    QDomDocument doc;

    // 添加 XML 声明
    QDomProcessingInstruction header = doc.createProcessingInstruction(
        "xml", "version=\"1.0\" encoding=\"UTF-8\"");
    doc.appendChild(header);

    // 创建根节点
    QDomElement root = doc.createElement("Root");
    doc.appendChild(root);

    // 添加子节点
    QDomElement child1 = doc.createElement("Child1");
    child1.setAttribute("attr", "value1");
    QDomText text1 = doc.createTextNode("Hello World");
    child1.appendChild(text1);
    root.appendChild(child1);

    QDomElement child2 = doc.createElement("Child2");
    child2.setAttribute("attr", "value2");
    QDomText text2 = doc.createTextNode("Qt XML");
    child2.appendChild(text2);
    root.appendChild(child2);

    // 写入文件
    QFile file(filePath);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        qDebug() << "Failed to open file for writing";
        return;
    }

    QTextStream stream(&file);
    stream.setCodec("UTF-8");
    doc.save(stream, 4); // 缩进为4空格
    file.close();
}

二、使用 QXmlStreamReader/QXmlStreamWriter(流式模型)

适合大规模 XML 文件,内存占用低,但只能顺序访问。

1. 解析 XML 文件

#include <QFile>
#include <QXmlStreamReader>
#include <QDebug>

void parseXmlWithStream(const QString& filePath) {
    QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qDebug() << "Failed to open file";
        return;
    }

    QXmlStreamReader reader(&file);
    while (!reader.atEnd()) {
        QXmlStreamReader::TokenType type = reader.readNext();

        switch (type) {
        case QXmlStreamReader::StartDocument:
            qDebug() << "XML Version:" << reader.documentVersion();
            qDebug() << "Encoding:" << reader.documentEncoding();
            break;
        case QXmlStreamReader::StartElement:
            qDebug() << "Start element:" << reader.name();
            // 获取属性
            for (const auto& attr : reader.attributes()) {
                qDebug() << "Attribute:" << attr.name() << "=" << attr.value();
            }
            break;
        case QXmlStreamReader::Characters:
            if (!reader.isWhitespace()) {
                qDebug() << "Text:" << reader.text();
            }
            break;
        case QXmlStreamReader::EndElement:
            qDebug() << "End element:" << reader.name();
            break;
        default:
            break;
        }
    }

    if (reader.hasError()) {
        qDebug() << "XML error:" << reader.errorString();
    }

    file.close();
}

2. 构建 XML 文件

#include <QFile>
#include <QXmlStreamWriter>
#include <QDebug>

void buildXmlWithStream(const QString& filePath) {
    QFile file(filePath);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        qDebug() << "Failed to open file for writing";
        return;
    }

    QXmlStreamWriter writer(&file);
    writer.setAutoFormatting(true);      // 自动格式化
    writer.setAutoFormattingIndent(2);   // 缩进2空格

    writer.writeStartDocument();         // 写入 XML 声明

    writer.writeStartElement("Root");    // 根节点

    writer.writeStartElement("Child1");
    writer.writeAttribute("attr", "value1");
    writer.writeCharacters("Hello World");
    writer.writeEndElement();            // </Child1>

    writer.writeStartElement("Child2");
    writer.writeAttribute("attr", "value2");
    writer.writeCharacters("Qt XML");
    writer.writeEndElement();            // </Child2>

    writer.writeEndElement();            // </Root>
    writer.writeEndDocument();           // 结束文档

    file.close();
}

三、项目配置

在 .pro 文件中添加 XML 模块:

QT += core xml

四、如何选择?

  • QDomDocument:适合小文件或需要随机访问的场景。

  • QXmlStreamReader/QXmlStreamWriter:适合大文件或顺序读写场景,性能更高。

五、示例调用

int main() {
    // 构建 XML
    buildXmlWithDOM("test_dom.xml");
    buildXmlWithStream("test_stream.xml");

    // 解析 XML
    parseXmlWithDOM("test_dom.xml");
    parseXmlWithStream("test_stream.xml");

    return 0;
}

生成的xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<Root>
    <Child1 attr="value1">Hello World</Child1>
    <Child2 attr="value2">Qt XML</Child2>
</Root>

输出结果:

Root element: "Root"
Element: "Child1"
Attribute value: "value1"
Text: "Hello World"
Element: "Child2"
Attribute value: "value2"
Text: "Qt XML"

六、注意事项

  1. 编码问题:确保 XML 文件的编码(如 UTF-8)与解析器设置一致。

  2. 错误处理:始终检查文件是否成功打开,并处理 XML 解析错误。

  3. 性能:大文件优先选择流式模型(QXmlStreamReader/QXmlStreamWriter)。

如果需要更高级的功能(如 XPath 查询),可以结合第三方库(如 QtXmlPatterns)。

posted @ 2024-12-05 11:21  [BORUTO]  阅读(417)  评论(0)    收藏  举报