加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

XML实例

发布时间:2020-12-16 05:24:22 所属栏目:百科 来源:网络整理
导读:TinyXML是一个非常小巧简单的XML解析库,采用DOM方式来解析XML文件。不足的是它本身不支持DTD和XSL,但普通简单的XML使用需求还是可以满足了。 TinyXML由2个头文件四个CPP文件构成。继承结构如下: TiXmlBase TiXmlAttribute TiXmlNode TiXmlComment TiXmlDe

TinyXML是一个非常小巧简单的XML解析库,采用DOM方式来解析XML文件。不足的是它本身不支持DTD和XSL,但普通简单的XML使用需求还是可以满足了。

TinyXML由2个头文件四个CPP文件构成。继承结构如下:

  • TiXmlBase
    • TiXmlAttribute
    • TiXmlNode
      • TiXmlComment
      • TiXmlDeclaration
      • TiXmlDocument
      • TiXmlElement
      • TiXmlText
      • TiXmlUnknown
  • TiXmlHandle
  • TiXmlVisitor
    • TiXmlPrinter

要操作XML首先需要加载XML,很简单:

[cpp] view plain copy
  1. TiXmlDocumentdoc("demo.xml");
  2. doc.LoadFile();

一个更加真实的用例如下所示,加载一个XML文件然后显示内容到标准输出上。

//loadthenamedfileanddumpitsstructuretoSTDOUT
  • voiddump_to_stdout(constchar*pFilename)
  • {
  • TiXmlDocumentdoc(pFilename);
  • boolloadOkay=doc.LoadFile();
  • if(loadOkay)
  • printf("n%s:n",pFilename);
  • dump_to_stdout(&doc);//definedlater
  • }
  • else
  • printf("Failedtoloadfile"%s"n",108); color:inherit; line-height:14px"> }
  • 写个简单的Main函数

    intmain(void)
  • {
  • dump_to_stdout("example1.xml");
  • return0;

  • 读下面的文件

    <?xmlversion="1.0"?>
  • <Hello>World</Hello>
  • 输出如下

    DECLARATION
  • +ELEMENTHello
  • +TEXT[World]
  • dump_to_stdout递归遍历输出所有的XML内容,详细实现在本文的末尾。

    TinyXML同样可以简单的编程生成一个上面的XML:

    voidbuild_simple_doc()
  • //Makexml:<?xml..><Hello>World</Hello>
  • TiXmlDocumentdoc;
  • TiXmlDeclaration*decl=newTiXmlDeclaration("1.0","","");
  • TiXmlElement*element=newTiXmlElement("Hello");
  • TiXmlText*text=newTiXmlText("World");
  • element->LinkEndChild(text);
  • doc.LinkEndChild(decl);
  • doc.LinkEndChild(element);
  • doc.SaveFile("madeByHand.xml");
  • }
  • 与其等价的写法:

    voidwrite_simple_doc2()
  • //sameaswrite_simple_doc1butaddeachnode
  • //asearlyaspossibleintothetree.
  • doc.LinkEndChild(decl);
  • doc.LinkEndChild(element);
  • doc.SaveFile("madeByHand2.xml");
  • 给定一个节点,设置它的属性也很简单:

    window=newTiXmlElement("Demo");
  • window->SetAttribute("name","Circle");
  • window->SetAttribute("x",5);
  • window->SetAttribute("y",15);
  • window->SetDoubleAttribute("radius",3.14159);
  • 可以用下面的函数获得元素的所有属性:

    //printallattributesofpElement.
  • //returnsthenumberofattributesprinted
  • intdump_attribs_to_stdout(TiXmlElement*pElement,unsignedintindent)
  • if(!pElement)return0;
  • TiXmlAttribute*pAttrib=pElement->FirstAttribute();
  • inti=0;
  • intival;
  • doubledval;
  • constchar*pIndent=getIndent(indent);
  • printf("n");
  • while(pAttrib)
  • printf("%s%s:value=[%s]",pIndent,pAttrib->Name(),pAttrib->Value());
  • if(pAttrib->QueryIntValue(&ival)==TIXML_SUCCESS)printf("int=%d",ival);
  • if(pAttrib->QueryDoubleValue(&dval)==TIXML_SUCCESS)printf("d=%1.1f",dval);
  • printf("n");
  • i++;
  • pAttrib=pAttrib->Next();
  • }
  • returni;
  • 我们经常通过配置文件来保存程序的一些配置信息。下面给一个实例来用XML加载和保存C++对象。

    #include<string>
  • #include<map>
  • usingnamespacestd;
  • typedefstd::map<std::string,std::string>MessageMap;
  • //abasicwindowabstraction-demopurposesonly
  • classWindowSettings
  • public:
  • intx,y,w,h;
  • stringname;
  • WindowSettings()
  • :x(0),y(0),w(100),h(100),name("Untitled")
  • }
  • WindowSettings(intx,inty,intw,inth,conststring&name)
  • this->x=x;
  • this->y=y;
  • this->w=w;
  • this->h=h;
  • this->name=name;
  • };
  • classConnectionSettings
  • public:
  • stringip;
  • doubletimeout;
  • };
  • classAppSettings
  • stringm_name;
  • MessageMapm_messages;
  • list<WindowSettings>m_windows;
  • ConnectionSettingsm_connection;
  • AppSettings(){}
  • voidsave(constchar*pFilename);
  • voidload(constchar*pFilename);
  • //justtoshowhowtodoit
  • voidsetDemoValues()
  • m_name="MyApp";
  • m_messages.clear();
  • m_messages["Welcome"]="Welcometo"+m_name;
  • m_messages["Farewell"]="Thankyouforusing"+m_name;
  • m_windows.clear();
  • m_windows.push_back(WindowSettings(15,15,400,250,"Main"));
  • m_connection.ip="Unknown";
  • m_connection.timeout=123.456;
  • };
  • 类AppSettings提供了保存和加载配置信息的函数save和load。如下代码表示利用缺省的配置保存和加载:

    AppSettingssettings;
  • settings.save("appsettings2.xml");
  • settings.load("appsettings2.xml");
  • 同样的我们可以运行时修改配置:

    //block:customiseandsavesettings
  • settings.m_name="HitchHikerApp";
  • settings.m_messages["Welcome"]="Don'tPanic";
  • settings.m_messages["Farewell"]="Thanksforallthefish";
  • settings.m_windows.push_back(WindowSettings(15,25,300,"BookFrame"));
  • settings.m_connection.ip="192.168.0.77";
  • settings.m_connection.timeout=42.0;
  • //block:loadsettings
  • AppSettingssettings;
  • settings.load("appsettings2.xml");
  • printf("%s:%sn",settings.m_name.c_str(),
  • settings.m_messages["Welcome"].c_str());
  • WindowSettings&w=settings.m_windows.front();
  • printf("%s:Showwindow'%s'at%d,%d(%dx%d)n",
  • settings.m_name.c_str(),w.name.c_str(),w.x,w.y,w.w,w.h);
  • printf("%s:%sn",settings.m_messages["Farewell"].c_str());
  • 有很多方法可以保存对象的属性信息,也就是对象的状态信息。下面的实例展示如何将对象的状态编码进XML文件。

    voidAppSettings::save(constchar*pFilename)
  • TiXmlDocumentdoc;
  • TiXmlElement*msg;
  • TiXmlComment*comment;
  • strings;
  • TiXmlElement*root=newTiXmlElement(m_name.c_str());
  • doc.LinkEndChild(root);
  • comment=newTiXmlComment();
  • s="Settingsfor"+m_name+"";
  • comment->SetValue(s.c_str());
  • root->LinkEndChild(comment);
  • //block:messages
  • MessageMap::iteratoriter;
  • TiXmlElement*msgs=newTiXmlElement("Messages");
  • root->LinkEndChild(msgs);
  • for(iter=m_messages.begin();iter!=m_messages.end();iter++)
  • conststring&key=(*iter).first;
  • conststring&value=(*iter).second;
  • msg=newTiXmlElement(key.c_str());
  • msg->LinkEndChild(newTiXmlText(value.c_str()));
  • msgs->LinkEndChild(msg);
  • //block:windows
  • TiXmlElement*windowsNode=newTiXmlElement("Windows");
  • root->LinkEndChild(windowsNode);
  • list<WindowSettings>::iteratoriter;
  • for(iter=m_windows.begin();iter!=m_windows.end();iter++)
  • constWindowSettings&w=*iter;
  • TiXmlElement*window;
  • window=newTiXmlElement("Window");
  • windowsNode->LinkEndChild(window);
  • window->SetAttribute("name",w.name.c_str());
  • window->SetAttribute("x",w.x);
  • window->SetAttribute("y",w.y);
  • window->SetAttribute("w",w.w);
  • window->SetAttribute("h",w.h);
  • //block:connection
  • TiXmlElement*cxn=newTiXmlElement("Connection");
  • root->LinkEndChild(cxn);
  • cxn->SetAttribute("ip",m_connection.ip.c_str());
  • cxn->SetDoubleAttribute("timeout",m_connection.timeout);
  • doc.SaveFile(pFilename);
  • 下面的示例展示如何从XML文件中获得对象的状态信息:

    voidAppSettings::load( TiXmlDocumentdoc(pFilename);
  • if(!doc.LoadFile())return;
  • TiXmlHandlehDoc(&doc);
  • TiXmlElement*pElem;
  • TiXmlHandlehRoot(0);
  • //block:name
  • pElem=hDoc.FirstChildElement().Element();
  • //shouldalwayshaveavalidrootbuthandlegracefullyifitdoes
  • if(!pElem) m_name=pElem->Value();
  • //savethisforlater
  • hRoot=TiXmlHandle(pElem);
  • //block:stringtable
  • m_messages.clear();//trashexistingtable
  • pElem=hRoot.FirstChild("Messages").FirstChild().Element();
  • for(pElem;pElem;pElem=pElem->NextSiblingElement())
  • constchar*pKey=pElem->Value();
  • constchar*pText=pElem->GetText();
  • if(pKey&&pText)
  • m_messages[pKey]=pText;
  • m_windows.clear();//trashexistinglist
  • TiXmlElement*pWindowNode=hRoot.FirstChild("Windows").FirstChild().Element();
  • for(pWindowNode;pWindowNode;pWindowNode=pWindowNode->NextSiblingElement())
  • WindowSettingsw;
  • constchar*pName=pWindowNode->Attribute("name");
  • if(pName)w.name=pName;
  • pWindowNode->QueryIntAttribute("x",&w.x);//Ifthisfails,originalvalueisleftas-is
  • pWindowNode->QueryIntAttribute("y",&w.y);
  • pWindowNode->QueryIntAttribute("w",&w.w);
  • pWindowNode->QueryIntAttribute("hh",&w.h);
  • m_windows.push_back(w);
  • pElem=hRoot.FirstChild("Connection").Element();
  • if(pElem)
  • m_connection.ip=pElem->Attribute("ip");
  • pElem->QueryDoubleAttribute("timeout",&m_connection.timeout);
  • 函数dump_to_stdout如下:

    #include"stdafx.h"
  • #include"tinyxml.h"
  • //----------------------------------------------------------------------
  • //STDOUTdumpandindentingutilityfunctions
  • constunsignedintNUM_INDENTS_PER_SPACE=2;
  • constchar*getIndent(unsignedintnumIndents)
  • staticconstchar*pINDENT="+";
  • constunsignedintLENGTH=strlen(pINDENT);
  • unsignedintn=numIndents*NUM_INDENTS_PER_SPACE;
  • if(n>LENGTH)n=LENGTH;
  • return&pINDENT[LENGTH-n];
  • //sameasgetIndentbutno"+"attheend
  • constchar*getIndentAlt(unsignedintnumIndents)
  • constchar*pINDENT="";
  • constunsignedintLENGTH=strlen(pINDENT);
  • unsignedintn=numIndents*NUM_INDENTS_PER_SPACE;
  • if(n>LENGTH)n=LENGTH;
  • return&pINDENT[LENGTH-n];
  • intdump_attribs_to_stdout(TiXmlElement*pElement,unsignedintindent)
  • TiXmlAttribute*pAttrib=pElement->FirstAttribute();
  • inti=0;
  • intival;
  • doubledval;
  • constchar*pIndent=getIndent(indent);
  • while(pAttrib)
  • printf("%s%s:value=[%s]",pAttrib->Value());
  • i++;
  • pAttrib=pAttrib->Next();
  • returni;
  • voiddump_to_stdout(TiXmlNode*pParent,unsignedintindent=0)
  • if(!pParent)return;
  • TiXmlNode*pChild;
  • TiXmlText*pText;
  • intt=pParent->Type();
  • printf("%s",getIndent(indent));
  • intnum;
  • switch(t)
  • caseTiXmlNode::TINYXML_DOCUMENT:
  • printf("Document");
  • break;
  • caseTiXmlNode::TINYXML_ELEMENT:
  • printf("Element[%s]",pParent->Value());
  • num=dump_attribs_to_stdout(pParent->ToElement(),indent+1);
  • switch(num)
  • case0:printf("(Noattributes)");break;
  • case1:printf("%s1attribute",getIndentAlt(indent));default:printf("%s%dattributes",getIndentAlt(indent),num);caseTiXmlNode::TINYXML_COMMENT:
  • printf("Comment:[%s]",pParent->Value());
  • caseTiXmlNode::TINYXML_UNKNOWN:
  • printf("Unknown");
  • caseTiXmlNode::TINYXML_TEXT:
  • pText=pParent->ToText();
  • printf("Text:[%s]",pText->Value());
  • caseTiXmlNode::TINYXML_DECLARATION:
  • printf("Declaration");
  • default:
  • for(pChild=pParent->FirstChild();pChild!=0;pChild=pChild->NextSibling())
  • dump_to_stdout(pChild,indent+1);
  • //loadthenamedfileanddumpitsstructuretoSTDOUT
  • boolloadOkay=doc.LoadFile();
  • if(loadOkay)
  • printf("n%s:n",pFilename);
  • dump_to_stdout(&doc);//definedlaterinthetutorial
  • 如果你想在MFC中使用TinyXML,会出现这样的编译错误fatal error C1010: unexpected end of file while looking for precompiled header。因为预编译头文件通过编译stdafx.cpp生成,可以在4个实现CPP文件中引入头#include "stdafx.h"。记得放在最前面。这样就可以编译通过了。

    (编辑:李大同)

    【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    • 推荐文章
        热点阅读