Qt的Xml操作QDomDocument
Qt對于Xml的支持是很好的,一些我們需要的操作應有盡有,下面簡單介紹一下怎樣使用。主要有以下幾點使用:
- 寫xml到文件
- 讀xml
- 添加節點到xml
- 刪除xml中某節點信息
- 修改xml中某節點信息
準備工作
- .pro加入QT += xml
- 需要include QDomDocument QTextStream QFile三個頭文件
WriteXml
直接上代碼
void writeXml()
{QDomDocument doc;QDomProcessingInstruction xmlInstruction = doc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"");QDomComment comment = doc.createComment(QString::fromLocal8Bit("離開是為了更好的歸來"));QDomProcessingInstruction styleInstruction = doc.createProcessingInstruction("xml-stylesheet", "type=\"text/css\" href=\"style.css\"");doc.appendChild(xmlInstruction); // 開始文檔(XML 聲明)doc.appendChild(comment); // 注釋doc.appendChild(styleInstruction); // 處理指令// 根元素 <Blogs>QDomElement root = doc.createElement("Books");root.setAttribute("Version", "1.0"); // 屬性doc.appendChild(root);// 元素 <Blog>QDomElement child = doc.createElement("Book");root.appendChild(child);// 元素 <作者>、<時間>、<個人說明>QDomElement author = doc.createElement(QString::fromLocal8Bit("作者"));QDomElement home = doc.createElement(QString::fromLocal8Bit("時間"));QDomElement instruction = doc.createElement(QString::fromLocal8Bit("個人說明"));child.appendChild(author);child.appendChild(home);child.appendChild(instruction);// 元素的文本數據QDomText authorText = doc.createTextNode(QString::fromLocal8Bit("Vincent"));QDomText homeText = doc.createTextNode("2017年4月13日");QDomText instructionText = doc.createTextNode(QString::fromLocal8Bit("大宋樞密院常任委員會_委員"));author.appendChild(authorText);home.appendChild(homeText);instruction.appendChild(instructionText);// 保存 XML 文件QString strFile("Books.xml");QFile file(strFile);// 只寫模式打開文件if (file.open(QFile::WriteOnly | QFile::Text)){QTextStream out(&file);doc.save(out, QDomNode::EncodingFromDocument);file.close();}
}
void writeXML()
{//打開或創建文件QString fileName{"test.xml"};QFile file(fileName);//QIODevice::Truncate表示清空原來的內容if(!file.open(QFile::WriteOnly|QFile::Truncate))return;//創建xml文檔在內存中QDomDocument doc;//添加處理命令QDomProcessingInstruction instruction;instruction = doc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\"");//創建注釋QDomComment comment;comment = doc.createComment(QString::fromLocal8Bit("離開是為了更好的歸來"));QDomProcessingInstruction styleInstruction;styleInstruction= doc.createProcessingInstruction("xml-stylesheet", "type=\"text/css\" href=\"style.css\"");doc.appendChild(instruction); //文檔開始聲明doc.appendChild(comment);doc.appendChild(styleInstruction); // 處理指令//添加根節點QDomElement root=doc.createElement("library");root.setAttribute("Version","2.1");doc.appendChild(root);//添加第一個子節點及其子元素QDomElement book=doc.createElement("book");//方式一:創建屬性 其中鍵值對的值可以是各種類型book.setAttribute("id",1);//方式二:創建屬性 值必須是字符串QDomAttr time=doc.createAttribute("time");time.setValue("2013/6/13");book.setAttributeNode(time);QDomElement title=doc.createElement("title"); //創建子元素QDomText text; //設置括號標簽中間的值text=doc.createTextNode("C++ primer");book.appendChild(title);title.appendChild(text);QDomElement author=doc.createElement("author"); //創建子元素text=doc.createTextNode("Stanley Lippman");author.appendChild(text);book.appendChild(author);//添加節點book做為根節點的子節點root.appendChild(book);//添加第二個子節點及其子元素book=doc.createElement("book");book.setAttribute("id",2);time=doc.createAttribute("time");time.setValue("2007/5/25");book.setAttributeNode(time);title=doc.createElement("title");text=doc.createTextNode("Thinking in Java");book.appendChild(title);title.appendChild(text);author=doc.createElement("author");text=doc.createTextNode("Bruce Eckel");author.appendChild(text);book.appendChild(author);root.appendChild(book);//輸出到文件QTextStream out_stream(&file);doc.save(out_stream,4); //縮進4格file.close();
}
ReadXml
上代碼
void readXML()
{//打開或創建文件QFile file("test.xml");if(!file.open(QFile::ReadOnly))return;QDomDocument doc;//設置wangfei1.xml到文檔if(!doc.setContent(&file)){file.close();return;}file.close();//返回根節點QDomElement root=doc.documentElement();qDebug()<<root.nodeName();//如果xml根元素有屬性(Version)將輸出,Vinsion是用戶自定義的屬性,沒有繼續執行下一條命令if (root.hasAttribute("Version")) // 屬性qDebug() << root.attribute("Version");/**********根元素之上(XML 聲明、注釋等)**********/QDomNode node = root.previousSibling();while (!node.isNull()){switch (node.nodeType()){case QDomNode::ProcessingInstructionNode :{QDomProcessingInstruction instruction = node.toProcessingInstruction();//輸出處理指令,是用戶自定義的,比如字符串“name”對應處理指令得到名字,這個命令是用戶寫的qDebug() << instruction.target() << instruction.data();if (QString::compare(instruction.target(), "xml") == 0) // 開始文檔(XML 聲明){//cout<<"處理命令xml"<<endl;// ...}else if (QString::compare(instruction.target(), "xml-stylesheet") == 0) // 處理指令{//cout<<"處理命令xml-stylesheet"<<endl;// ...}break;}case QDomNode::CommentNode :{QDomComment comment = node.toComment();qDebug() << comment.data();break;}default:break;}node = node.previousSibling();}//獲得第一個子節點node=root.firstChild();while(!node.isNull()) //如果節點不空{if(node.isElement()) //如果節點是元素{//轉換為元素QDomElement element=node.toElement();if (!element.isNull())// 節點的確是一個元素{//輸出第一個節點,包括第一個節點的屬性,這個屬性需要指定屬性值,才能輸出,如果沒有輸出空qDebug()<<element.tagName()<<" "<<element.attribute("id")<<" "<<element.attribute("time");QDomNodeList list=element.childNodes();for(int i=0;i<list.count();++i){QDomNode n=list.at(i);//node = list.at(i);if(node.isElement()){qDebug()<<n.nodeName()<<":"<<n.toElement().text();element = n.toElement();//qDebug()<<element.nodeName()<<":"<<element.toElement().text();if (QString::compare(element.tagName(), QStringLiteral("作者")) == 0){// ...處理命令//cout<< "處理命令作者"<<endl;}else if (QString::compare(element.tagName(), QStringLiteral("時間")) == 0){//cout<<"處理命令時間"<<endl;// ...處理命令}else if (QString::compare(element.tagName(), QStringLiteral("個人說明")) == 0){//cout<<"處理命令個人說明"<<endl;// ...處理命令}}}}}//下一個兄弟節點node=node.nextSibling();}
}
AddXml
void addXML()
{//打開文件QFile file("test.xml");if(!file.open(QFile::ReadOnly))return;//增加一個一級子節點以及元素QDomDocument doc;if(!doc.setContent(&file)){file.close();return;}file.close();//創建根節點QDomElement root = doc.documentElement();//創建next子節點bookQDomElement book = doc.createElement("book");book.setAttribute("id",3);book.setAttribute("time","1813/1/27");QDomElement title = doc.createElement("title");QDomText text;text = doc.createTextNode("Pride and Prejudice");//添加text內容到title節點title.appendChild(text);//添加title到book節點book.appendChild(title);//添加book到根節點root.appendChild(book);if(!file.open(QFile::WriteOnly|QFile::Truncate))return;//輸出到文件QTextStream out_stream(&file);doc.save(out_stream,4); //以縮進4格方式輸出,也有其他輸出方式(格式)file.close();
}
DeleteXml
void deleteXML()
{//打開文件QFile file("test.xml");if(!file.open(QFile::ReadOnly))return;//刪除一個一級子節點及其元素,外層節點刪除內層節點于此相同QDomDocument doc;if(!doc.setContent(&file)){file.close();return;}file.close();QDomElement root=doc.documentElement();//由標簽名定位,本標簽為book,以后可以是用string類型的字符串替換,實現動態QDomNodeList list=doc.elementsByTagName("book");//刪除方式一,通過標簽book后面的屬性刪除<book>到</book>for(int i=0;i<list.count();i++){//轉化為元素QDomElement e=list.at(i).toElement();//找到time是2007/5/25這一條數據將其刪除if(e.attribute("time")=="2007/5/25")root.removeChild(list.at(i));}//刪除方式二,可以通過索引直接刪除
// root.removeChild(list.at(1));if(!file.open(QFile::WriteOnly|QFile::Truncate))return;//輸出到文件QTextStream out_stream(&file);doc.save(out_stream,4); //縮進4格file.close();
}
AmendXml
void amendXML()
{//打開文件QFile file("wangfei1.xml");if(!file.open(QFile::ReadOnly))return;//更新一個標簽項,如果知道xml的結構,直接定位到那個標簽上定點更新//或者用遍歷的方法去匹配tagname或者attribut,value來更新QDomDocument doc;//設置wangfei.xml讀到doc文檔if(!doc.setContent(&file)){file.close();return;}file.close();/*** 知道xml結構,直接定位修改* 提取根節點**/QDomElement root=doc.documentElement();//以book標簽存入list
// QDomNodeList list=root.elementsByTagName("book");
// QDomNode listNode=list.at(list.size()-2).firstChild();
// QDomNode oldnode=listNode.firstChild();
// //把title改成Emma
// listNode.firstChild().setNodeValue("aaaaaaa");
// QDomNode newnode=listNode.firstChild();
// listNode.replaceChild(newnode,oldnode);//使用遍歷方法選擇要修改的元素
// QDomNodeList lists =doc.childNodes();
// QDomNodeList list=root.elementsByTagName("book");QDomNode node = root.firstChild();//QDomNodeList list=root.elementsByTagName("book");while(!node.isNull()) //如果節點不空{if(node.isElement()) //如果節點是元素{//轉換為元素QDomElement element=node.toElement();if (!element.isNull() && element.attribute("id") == "3")// 節點的確是一個元素{//輸出第一個節點,包括第一個節點的屬性,這個屬性需要指定屬性值,才能輸出,如果沒有輸出空//qDebug()<<element.tagName()<<" "<<element.attribute("id")<<" "<<element.attribute("time");QDomNodeList list=element.childNodes();for(int i=0;i<list.count();++i){QDomNode n=list.at(i);//node = list.at(i);if(node.isElement()){//qDebug()<<n.nodeName()<<":"<<n.toElement().text();element = n.toElement();//與上面qDebug效果相同//qDebug()<<element.nodeName()<<":"<<element.toElement().text();//這個if可以不需要,如果需要精確定位,以防數據相同所以要加這個嵌套ifif (QString::compare(element.tagName(), QStringLiteral("title")) == 0){if("Pride and Prejudice" == element.toElement().text()){// ...處理命令,在這個if里可以遍歷想要的節點進行修改//新建一個舊的node緩存QDomNode oldNode = n.firstChild();n.firstChild().setNodeValue("changchun1");//新建一個新的newNode子節點QDomNode newNode = n.firstChild();//使用replaceChild替換noden.replaceChild(newNode,oldNode);}}else if (QString::compare(element.tagName(), QStringLiteral("時間")) == 0){//cout<<"處理命令時間"<<endl;// ...處理命令}else if (QString::compare(element.tagName(), QStringLiteral("個人說明")) == 0){//cout<<"處理命令個人說明"<<endl;// ...處理命令}}}}}//下一個兄弟節點node=node.nextSibling();}if(!file.open(QFile::WriteOnly|QFile::Truncate))return;//輸出到文件QTextStream out_stream(&file);doc.save(out_stream,4); //縮進4格file.close();}