QT中对XML的处理

QT自带例子:

C:\Qt\Qt5.5.1\Examples\Qt-5.5\widgets\itemviews\simpledommodel\simpledommodel.pro

C:\Qt\Qt5.5.1\Examples\Qt-5.5\xml\dombookmarks\dombookmarks.pro

http://blog.sina.com.cn/s/blog_a6fb6cc90101eupl.html

如何使用QXmlStreamReader来解析格式良好的XML,Qt的文档中指出,它是一种更快、更方便的Qt己的SAX解析器(QXmlSimpleReader)的替代,它也较快,在某种情况下,比DOM(QDomDocument)更方便。

下面是对 QXmlStreamReader 读取XML格式的原理探讨图,下面是对 以<和>为分界线对XML进行解析(除了刚开始的注释外)


<?xml version="1.0" encoding="UTF-8"?>
<persons name="Qt">
<person id="1">
<name>wang</name>
<age>24</age>
<email>wang@sina.com</email>
<website>www.wang.com</website>
</person>
<person id="2">
<name>sugon</name>
<age>25</age>
<email>sugon@sina.com</email>
<website>www.sugon.com</website>
</person>       
</persons>
Starting E:\delcode\build-untitled-Desktop_Qt_5_5_1_MSVC2010_32bit-Debug\debug\untitled.exe...
[wificommon]开始进入....readNext before: 1 0
readNext after: 1 38 "StartDocument"
readNext before: 1 38
readNext after: 2 19 "StartElement"
readNext before: 2 19
readNext after: 3 1 "Characters"
readNext before: 3 1
readNext after: 3 15 "StartElement"
readNext before: 3 15
readNext after: 4 1 "Characters"
readNext before: 4 1
readNext after: 4 6 "StartElement"
readNext before: 4 6
readNext after: 4 11 "Characters"
readNext before: 4 11
readNext after: 4 17 "EndElement"
readNext before: 4 17
readNext after: 5 1 "Characters"
readNext before: 5 1
readNext after: 5 5 "StartElement"
readNext before: 5 5
readNext after: 5 8 "Characters"
readNext before: 5 8
readNext after: 5 13 "EndElement"
readNext before: 5 13
readNext after: 6 1 "Characters"
readNext before: 6 1
readNext after: 6 7 "StartElement"
readNext before: 6 7
readNext after: 6 21 "Characters"
readNext before: 6 21
readNext after: 6 28 "EndElement"
readNext before: 6 28
readNext after: 7 1 "Characters"
readNext before: 7 1
readNext after: 7 9 "StartElement"
readNext before: 7 9
readNext after: 7 22 "Characters"
readNext before: 7 22
readNext after: 7 31 "EndElement"
readNext before: 7 31
readNext after: 8 1 "Characters"
readNext before: 8 1
readNext after: 8 9 "EndElement"
readNext before: 8 9
readNext after: 9 1 "Characters"
readNext before: 9 1
readNext after: 9 15 "StartElement"
readNext before: 9 15
readNext after: 10 1 "Characters"
readNext before: 10 1
readNext after: 10 6 "StartElement"
readNext before: 10 6
readNext after: 10 12 "Characters"
readNext before: 10 12
readNext after: 10 18 "EndElement"
readNext before: 10 18
readNext after: 11 1 "Characters"
readNext before: 11 1
readNext after: 11 5 "StartElement"
readNext before: 11 5
readNext after: 11 8 "Characters"
readNext before: 11 8
readNext after: 11 13 "EndElement"
readNext before: 11 13
readNext after: 12 1 "Characters"
readNext before: 12 1
readNext after: 12 7 "StartElement"
readNext before: 12 7
readNext after: 12 22 "Characters"
readNext before: 12 22
readNext after: 12 29 "EndElement"
readNext before: 12 29
readNext after: 13 1 "Characters"
readNext before: 13 1
readNext after: 13 9 "StartElement"
readNext before: 13 9
readNext after: 13 23 "Characters"
readNext before: 13 23
readNext after: 13 32 "EndElement"
readNext before: 13 32
readNext after: 14 1 "Characters"
readNext before: 14 1
readNext after: 14 9 "EndElement"
readNext before: 14 9
readNext after: 15 1 "Characters"
readNext before: 15 1
readNext after: 15 10 "EndElement"
readNext before: 15 10
readNext after: 16 0 "EndDocument"

代码如下:

void MainWindow::parseXML(QString file_name)
{
    /*if(file_name.isEmpty())
        return;

    QFile *file = new QFile(file_name);
    if(!file->open(QFile::ReadOnly | QFile::Text))
    {
        QMessageBox::information(NULL, QString("title"), QString("open error!"));

        return;
    }

    //QXmlStreamReader操作任何QIODevice.
    QXmlStreamReader xml(file);
    QList<QMap<QString,QString> > persons;

    //解析XML,直到结束
    while(!xml.atEnd() && !xml.hasError())
    {
        //读取下一个element.
        qDebug()<<"readNext before:"<<xml.lineNumber()<<xml.columnNumber();
        QXmlStreamReader::TokenType token = xml.readNext();// <?xml version="1.0" encoding="UTF-8"?
        qDebug()<<"readNext after:"<<xml.lineNumber()<<xml.columnNumber()<<xml.tokenString();
    }

    if(xml.hasError())
    {
        QMessageBox::information(NULL, QString("parseXML"), xml.errorString());
    }

    //从reader中删除所有设备、数据,并将其重置为初始状态
    xml.clear();
    */

#if 1
    if(file_name.isEmpty())
        return;

    QFile *file = new QFile(file_name);
    if(!file->open(QFile::ReadOnly | QFile::Text))
    {
        QMessageBox::information(NULL, QString("title"), QString("open error!"));

        return;
    }

    //QXmlStreamReader操作任何QIODevice.
    QXmlStreamReader xml(file);
    QList<QMap<QString,QString> > persons;

    //解析XML,直到结束
    while(!xml.atEnd() && !xml.hasError())
    {
        //读取下一个element.
        //qDebug()<<xml.lineNumber()<<xml.columnNumber()<<xml.characterOffset();
        QXmlStreamReader::TokenType token = xml.readNext();// <?xml version="1.0" encoding="UTF-8"?
        //qDebug()<<xml.lineNumber()<<xml.columnNumber()<<xml.characterOffset();

        //如果获取的仅为StartDocument,则进行下一个  //! QXmlStreamReader::StartDocument ==  <?xml version="1.0" encoding="UTF-8"?>
        if(token == QXmlStreamReader::StartDocument)
        {
            //qDebug()<<"xml.documentVersion.toString()"<<xml.documentVersion().toString();
            //qDebug()<<"xml.documentEncoding.toString()"<<xml.documentEncoding().toString();

            continue;
        }

        //如果获取了StartElement,则尝试读取
        if(token == QXmlStreamReader::StartElement)
        {
            //如果为persons,直接进入下一个
            if(xml.name() == "persons" && xml.attributes().hasAttribute("name") ==true)
            {
                qDebug()<<xml.attributes().value("name").toString();
                continue;
            }

            //如果为person,则对其进行解析
            if(xml.name() == "person")
            {
                persons.append(this->parsePerson(xml));
            }
        }
    }
    qDebug()<<"persons="<<persons;

    if(xml.hasError())
    {
        QMessageBox::information(NULL, QString("parseXML"), xml.errorString());
    }

    //从reader中删除所有设备、数据,并将其重置为初始状态
    xml.clear();
#endif
}

QMap<QString,QString> MainWindow::parsePerson(QXmlStreamReader& xml)
{
    QMap<QString,QString>  person;

    //检查是否获取person
    //qDebug()<<"xml.name()="<<xml.name()<<xml.tokenType();
    if(xml.tokenType() != QXmlStreamReader::StartElement &&
            xml.name() == "person")
    {
        return person;
    }

    //获取person属性
    QXmlStreamAttributes attributes = xml.attributes();
    if(attributes.hasAttribute("id"))
    {
        person["id"] = attributes.value("id").toString();
    }

    //操作下一个
    xml.readNext();

    //qDebug()<<"readNext xml.name()="<<xml.name()<<xml.tokenType();
    while(!(xml.tokenType() == QXmlStreamReader::EndElement &&
            xml.name() == "person"))
    {
        if(xml.tokenType() == QXmlStreamReader::StartElement)
        {
            if(xml.name() == "name")
            {
                this->addElementDataToMap(xml, person);
            }

            if(xml.name() == "age")
            {
                this->addElementDataToMap(xml, person);
            }

            if(xml.name() == "email")
            {
                this->addElementDataToMap(xml, person);
            }

            if(xml.name() == "website")
            {
                this->addElementDataToMap(xml, person);
            }
        }

        xml.readNext();
    }

    QString id = person["id"];
    QString name = person["name"];
    QString age =  person["age"];
    QString email = person["email"];
    QString website = person["website"];

    return person;
}

void MainWindow::addElementDataToMap(QXmlStreamReader& xml,
                                   QMap<QString, QString>& map) const
{
    if(xml.tokenType() != QXmlStreamReader::StartElement)
    {
        return;
    }

    QString elementName = xml.name().toString();
    xml.readNext();

    if(xml.tokenType() != QXmlStreamReader::Characters)
    {
        return;
    }

    map.insert(elementName, xml.text().toString());
}

void MainWindow::on_tx_clicked()
{
    //QFile file("C:\Users\Administrator\Desktop\image\\test.xml");
    parseXML("C:\\Users\\Administrator\\Desktop\\image\\test.xml");
//    file.open(QFile::ReadOnly | QFile::Text);
//    xml.setDevice(&file);
//    int icnt = 0;
}

void MainWindow::on_tx_clicked()
{
    //QFile file("C:\Users\Administrator\Desktop\image\\test.xml");
    //parseXML("C:\\Users\\Administrator\\Desktop\\image\\test.xml");
//    file.open(QFile::ReadOnly | QFile::Text);
//    xml.setDevice(&file);
//    int icnt = 0;
    QFile file("C:\\Users\\Administrator\\Desktop\\image\\test1.xml");
    file.open(QFile::WriteOnly | QFile::Text);
    writeFile(&file);
}

//! [1]
bool MainWindow::writeFile(QIODevice *device)
{
    wxml.setAutoFormatting(true);
    wxml.setDevice(device);
    wxml.writeStartDocument();
    wxml.writeDTD("<!DOCTYPE xbel>");//! xml 的解析方式为 xbel
    wxml.writeStartElement("xx");
    wxml.writeAttribute("folded", "yes" );
    wxml.writeTextElement("title", "12345");
    wxml.writeEmptyElement("hello");
    wxml.writeEndElement();
    wxml.writeEndDocument();

    return true;
}

效果如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xbel>
<xx folded="yes">
    <title>12345</title>
    <hello/>
</xx>

写也可以通过流的方式,更加简单,如下所示:

class XmlStreamLint
{
public:
    Q_DECLARE_TR_FUNCTIONS(XmlStreamLint)
};

int main(int argc, char *argv[])
{
    enum ExitCode
    {
        Success,
        ParseFailure,
        ArgumentError,
        WriteError,
        FileFailure
    };

    QCoreApplication app(argc, argv);

    QTextStream errorStream(stderr);

    if (argc != 2)
    {
        errorStream << XmlStreamLint::tr(
                       "Usage: xmlstreamlint <path to XML file>\n");
        return ArgumentError;
    }

    QString inputFilePath(QCoreApplication::arguments().at(1));
    QFile inputFile(inputFilePath);

    if (!QFile::exists(inputFilePath))
    {
        errorStream << XmlStreamLint::tr(
                       "File %1 does not exist.\n").arg(inputFilePath);
        return FileFailure;

    } else if (!inputFile.open(QIODevice::ReadOnly)) {
        errorStream << XmlStreamLint::tr(
                       "Failed to open file %1.\n").arg(inputFilePath);
        return FileFailure;
    }

    QFile outputFile("C:\\Users\\Administrator\\Desktop\\image\\test2.xml");
    if (!outputFile.open( QIODevice::WriteOnly))
    {
        errorStream << XmlStreamLint::tr("Failed to open stdout.");
        return WriteError;
    }

//    QFile outputFile;
//    if (!outputFile.open(stdout, QIODevice::WriteOnly))
//    {
//        errorStream << XmlStreamLint::tr("Failed to open stdout.");
//        return WriteError;
//    }

//! [0]
    QXmlStreamReader reader(&inputFile);
    QXmlStreamWriter writer(&outputFile);
//! [0]

//! [1]
    while (!reader.atEnd())
    {
        reader.readNext();

        if (reader.error())
        {
            errorStream << XmlStreamLint::tr(
                           "Error: %1 in file %2 at line %3, column %4.\n").arg(
                               reader.errorString(), inputFilePath,
                               QString::number(reader.lineNumber()),
                               QString::number(reader.columnNumber()));
            return ParseFailure;
//! [1]

//! [2]
        } else
            writer.writeCurrentToken(reader);
    }
//! [2]

    return Success;
}



readXmlFile(m_initFolderPath+"/"+m_xmlFileName);void MainWindow::readXmlFile(QString fileName)
{
    QFile file(fileName);
    if(!file.open(QFile::ReadOnly | QFile::Text))
    {
        qDebug()<<"open file"<<fileName<<"failed, error:"<<file.errorString();
        return;
    }
    QDomDocument    document;
    QString         strError;
    int errLin = 0, errCol = 0;
    if( !document.setContent(&file, false, &strError, &errLin, &errCol) )
    {
        qDebug()<<"parse file failed at line"<<errLin<<",column"<<errCol<<","<<strError;
        return;
    }

    if( document.isNull() )
    {
        qDebug()<<"document is null !";
        return;
    }

    QDomElement root = document.documentElement();
    qDebug()<<root.tagName();

    QDomElement catalogs = root.firstChildElement();
    if( catalogs.isNull() )
    {
        return;
    }
    else
    {
        //qDebug()<<catalogs.tagName();
    }
    while(!catalogs.isNull())
    {
        foreachElement(catalogs);
        catalogs = catalogs.nextSiblingElement();
    }
    file.close();
}

void MainWindow::foreachElement(QDomElement catalogs)
{
    if(catalogs.tagName()=="")
        return;
    //qDebug()<<catalogs.tagName();
    if(catalogs.hasAttributes())
    {
        QDomNamedNodeMap map = catalogs.attributes();
        if(catalogs.tagName()==NodeSystemButton)
        {
            createSystemButton(map);
        }
        else if(catalogs.tagName()==NodeSAction)
        {
            createSAction(map);
        }
        else if(catalogs.tagName()==NodeRibbonPageSystemPopup)
        {
            createRibbonPageSystemPopup(map);
        }
        else if(catalogs.tagName()==NodeSRAction)
        {
            createSRAction(map);
        }
        else if(catalogs.tagName()==NodeRibbonQuickAccessBar)
        {
            createQuickAccessBar(map);
        }
        else if(catalogs.tagName()==NodeExitsAction)
        {
            bindingExitsAction(map);
        }
        else if(catalogs.tagName()==NodeQuickAction)
        {
            createQuickAction(map);
        }
        else if(catalogs.tagName()==NodeRibbonPage)
        {
            createRibbonPage(map);
        }
        else if(catalogs.tagName()==NodeRibbonGroup)
        {
            createRibbonGroup(map);
        }
        else if(catalogs.tagName()==NodeOptionButtonAction)
        {
        }
        else if(catalogs.tagName()==NodeQMenu)
        {
            createPMenu(map);
        }
        else if(catalogs.tagName()==NodeQAction)
        {
            createPMQAction(map);
        }
        else if(catalogs.tagName()==NodePageQAction)
        {
            createPageQAction(map);
        }
        else if(catalogs.tagName()==NodeRibbonStatusBar)
        {
            createRibbonStatusBar();
        }
        else if(catalogs.tagName()==NodeStatusAction)
        {
            createStatusAction(map);
        }
    }
    if(catalogs.hasChildNodes())
    {
        for(int i=0;i<catalogs.childNodes().length();++i)
        {
            foreachElement(catalogs.childNodes().at(i).toElement());
        }
    }
}

QString MainWindow::getNodeValue(QDomNamedNodeMap map, QString key)
{
    QString tempValue=map.namedItem(key).nodeValue();
    if(key=="Icon")
        tempValue=m_initFolderPath+"/"+m_imageFolder+"/"+tempValue;
    return tempValue;

}


<?xml version="1.0" encoding="gb2312"?>
<xxx>
<!--0不显示此列 -->
<rrr>ttx1</rrr>
<tx test33="abc" test22="efg">1</tx>
</xxx>

QStringList  MainWindow::SMSDXmlGet(QDomNodeList &value)
{
    int cnt = value.count();
    for(int i=0;i<cnt;i++)
    {
        QDomNode childNode=value.at(i);
        QDomNode::NodeType ttype = childNode.nodeType();
        QString nodeName = childNode.nodeName();
        QString nodeValue= childNode.nodeValue();
        QDomElement elem = childNode.toElement();
        //elem.text();
        qDebug()  << "i==:" << i << "nodeName:" << nodeName << "nodeValue:" << nodeValue<< "NodeType:" << ttype<< "elem:" << elem.text();
    }
    QStringList ret;
    return ret;
}

QStringList  MainWindow::SMSDXmlGet(QDomNodeList &value)
{
    int cnt = value.count();
    for(int i=0;i<cnt;i++)
    {
        QDomNode childNode=value.at(i);
        QDomNode::NodeType ttype = childNode.nodeType();
        QString nodeName = childNode.nodeName();
        QString nodeValue= childNode.nodeValue();




        QDomNamedNodeMap attributeMap = childNode.attributes();
        QDomNode attribute = attributeMap.item(0);
        QString s1= attribute.nodeName();
        QString s2= attribute.nodeValue();
        int tt;
    }
    QStringList ret;
    return ret;
}


void MainWindow::pushButton_4Slot()
{
    int i=0;
    QString filePath="mytest.xml";
    QFile file(filePath);
    if (file.open(QIODevice::ReadOnly))
    {
        QDomDocument document;
        if (document.setContent(&file))
        {
            QDomNode &RootDomNode = document;
            int RootDomNodeChildsCnt = RootDomNode.childNodes().count();
                for(int i=1;i<RootDomNodeChildsCnt;i++)
            {
                QDomNode childNode = RootDomNode.childNodes().item(i);
                QDomElement ele = RootDomNode.firstChildElement("ServiceManageShowDlgSet");


               QDomNode ttx =  RootDomNode.namedItem("serviceCNName") ;
               QString sttx = ttx.nodeValue();
                QDomNodeList childList = ele.childNodes();
int cnt=childList.count();
                QStringList sRet= SMSDXmlGet(childList);
int tt=99;
//                int childListCnt = childList.count();
//                QString nodeName = childNode.nodeName();
//                QString nodeValue= childNode.nodeValue();
//                QDomNamedNodeMap attributeMap = childNode.attributes();
//                QDomNode attribute = attributeMap.item(i);
//                QString s1= attribute.nodeName();
//                QString s2= attribute.nodeValue();
            }
        }
        file.close();
    }
}

创建XML:

int main( int argc, char **argv )
{
 QApplication a( argc, argv );


 QDomDocument doc("MyML");
 QDomElement root = doc.createElement("MyML");
 doc.appendChild(root);


 QDomElement tag = doc.createElement("Greeting");
 root.appendChild(tag);


 QDomText t = doc.createTextNode("Hello World");
 tag.appendChild(t);


 QString xml = doc.toString();
//qDebug()<<"xml"<<xml;


QFile file("mydocument.xml"); //!  如果没有此XML,会自动创建,如果有此XML,会覆盖此XML
if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate |QIODevice::Text))
     return 0;
QTextStream out(&file);
out.setCodec("UTF-8");
doc.save(out,4,QDomNode::EncodingFromTextStream);
file.close();
return 0;
}


  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值