1. 程式人生 > >Qt:用Dom方式讀寫xml檔案

Qt:用Dom方式讀寫xml檔案

  網上有不少介紹Dom方式讀寫xml檔案,大部分給出的程式碼都不夠完整。這裡通過我做的的一個例子做一個完整的總結。XML檔案格式如下

<?xml version="1.0" encoding="UTF-8"?>
<RootSkeletonData>
    <RootNode>
        <X>77.3122</X>
        <Y>80.0328</Y>
        <Z>0</Z>
    </RootNode>
    <RootNode>
        <X>77.3154</X>
        <Y>80.0902</Y>
        <Z>0.5</Z>
    </RootNode>
<RootSkeletonData>
寫檔案:
bool SkeletonWriter::saveSkeletonData(QString filename,QList<RootNode> &nodes)
{
    //--[1]引數檢測
    if(nodes.isEmpty())
    {
        qDebug()<<"Error:skeleton Data is null!";
        return false;
    }

    QFile file(filename);
    if(!file.open(QFile::WriteOnly|QFile::Text))
    {
        qDebug()<<"Error: Cannot write file:"<<filename;
        return false;
    }
    //[1]

    //[2] --建立一個根目錄
    QDomElement root=doc->createElement("RootSkeletonData");
    doc->appendChild(root);
    //[2]

    //[3] --建立每一個根結點元素
    for(int i=0;i<nodes.size();++i)
        createNodeElement(&root,&nodes[i]);
    //[3]

    //[4] --xml檔案頭
    QDomNode xmlnode=doc->createProcessingInstruction("xml",
                                                     "version=\"1.0\"encoding=\"UTF-8\"");
    doc->insertBefore(xmlnode,doc->firstChild());
    //[4]

    //[5] --儲存
    QTextStream out(&file);
    out.setCodec("UTF-8");
    doc->save(out,4,QDomNode::EncodingFromTextStream);
    //[5]

    file.close();
    return true;
}

void SkeletonWriter::createNodeElement(QDomElement *element, RootNode *node)
{
    // --[1]create nodeelement
    QDomElement g_node=doc->createElement("RootNode");
    element->appendChild(g_node);
    //[1]

    // --[2] create 各個座標值
    QVector3D center=node->getCentroid();
    QDomElement nodeX=doc->createElement("X");
    g_node.appendChild(nodeX);
    QDomText X_Text=doc->createTextNode(QString::number(center.x()));

    nodeX.appendChild(X_Text);
    QDomElement nodeY=doc->createElement("Y");
    g_node.appendChild(nodeY);
    QDomText Y_Text=doc->createTextNode(QString::number(center.y()));
    nodeY.appendChild(Y_Text);

    QDomElement nodeZ=doc->createElement("Z");
    g_node.appendChild(nodeZ);
    QDomText Z_Text=doc->createTextNode(QString::number(center.z()));
    nodeZ.appendChild(Z_Text);
    //[2]
}
簡述:所有的標籤只能有QDomDocument通過createElement來建立,其生成一個QDomElement標籤元素。按照自己規劃的樹形結構,決定生成的新標籤到底要加入(appendChild)哪一個標籤下面。通過createTextNode可以建立一個文字標籤

讀檔案:

bool SkeletonReader::setFileName(QString filename)
{
    //[1] --檔案讀取檢測
    QFile file(filename);
    if(!file.open(QFile::ReadOnly|QFile::Text))
    {
        qDebug()<<"Error:Cannot readfile!"<<filename;
        return false;
    }
    //[1]

    //[2] --xml檔案解析檢測
    QDomDocument doc;
    QString errorStr;
    int errorLine;
    int errorColumn;
    if(!doc.setContent(&file,false,&errorStr,&errorLine,&errorColumn))
    {
        qDebug()<<"Error:Parse error at line:"<<errorLine<<","
               <<"at column:"<<errorColumn<<":"
              <<errorStr;

        file.close();
        return false;
    }

    QDomElement root=doc.documentElement();
    rootTagName=root.tagName();
    if(root.tagName()!="RootSkeletonData")
    {
        qDebug()<<"Not a rootSkeleton data file!";

        file.close();
        return false;
    }

    parseNodeElement(&root);

    file.close();
    return true;
}

void SkeletonReader::parseNodeElement(const QDomElement *element)
{
    QDomNode child =element->firstChild();
    while(!child.isNull())
    {
        parseCenterElement(&child.toElement());
        child=child.nextSibling();
    }
}

void SkeletonReader::parseCenterElement(const QDomElement *element)
{
    QDomNode child =element->firstChild();
    double center[3];
    while(!child.isNull())
    {
        if(child.toElement().tagName()=="X")
            center[0]=child.toElement().text().toDouble();
        if(child.toElement().tagName()=="Y")
            center[1]=child.toElement().text().toDouble();
        if(child.toElement().tagName()=="Z")
            center[2]=child.toElement().text().toDouble();

        child=child.nextSibling();
    }

    RootNode node;
    node.setCentroid(center);
    m_nodes<<node;
}

簡述:讀檔案 注意前面一系列的引數檢測。這裡買面反覆用的的幾個Dom相關的類分別是:QDomDocment、QDomNode、QDomElement、QDomText

其中QDomDocument類表示一個XML文件。該類可以生成新結點


QDomNode類是DOM樹中所有節點的基類。代表結點 該類儲存了結點之間的樹型拓撲關係

QDomElement類表示Element型別結點。存放元素類資料(一對標籤組成)其繼承自QDomNode

QDomText類表示Text型別節點  存放文字資料   繼承自QDomNode

理清這幾個類就基本可以完成一個XML檔案的讀寫了


參考文獻: