C++中XML的读写操作(生成XML & 解析XML)

一、用Poco库

Poco库是下载、编译和使用:www.cnblogs.com/htj10/p/11380144.html

DOM(The Document Object Model)方式:

1. 生成XML

#include <Poco/AutoPtr.h>
#include <Poco/DOM/Document.h> //for Poco::XML::Document
#include <Poco/DOM/Element.h>  //for Poco::XML::Element
#include <Poco/DOM/Text.h>       //for Poco::XML::Text
#include <Poco/DOM/CDATASection.h>    //for Poco::XML::CDATASection
#include <Poco/DOM/ProcessingInstruction.h> //for Poco::XML::ProcessingInstruction
#include <Poco/DOM/Comment.h>  //for Poco::XML::Comment
#include <Poco/DOM/DOMWriter.h> //for Poco::XML::DOMWriter
#include <Poco/XML/XMLWriter.h> //for Poco::XML::XMLWriter
#include <sstream>

int main(int argc, char** argv)
{
    //Poco生成XML
    Poco::AutoPtr<Poco::XML::Document> pDoc = new Poco::XML::Document;
    Poco::AutoPtr<Poco::XML::ProcessingInstruction> pi = pDoc->createProcessingInstruction("xml","version='1.0' encoding='UTF-8'");
    Poco::AutoPtr<Poco::XML::Comment> pComment = pDoc->createComment("The information of some Universities.");
    Poco::AutoPtr<Poco::XML::Element> pRoot = pDoc->createElement("University_info");

    Poco::AutoPtr<Poco::XML::Element> pChild = pDoc->createElement("University");
    pChild->setAttribute("name", "Harvard");
    Poco::AutoPtr<Poco::XML::Element> pGrandchild1 = pDoc->createElement("school");
    pGrandchild1->setAttribute("name", "Secient");
    Poco::AutoPtr<Poco::XML::Element> pGrandchild2 = pDoc->createElement("school");
    pGrandchild2->setAttribute("name", "Mathematics");

    Poco::AutoPtr<Poco::XML::Element> pNumOfPeople = pDoc->createElement("people_counting");
    Poco::AutoPtr<Poco::XML::Text> pText = pDoc->createTextNode("123");
    pNumOfPeople->appendChild(pText);
    Poco::AutoPtr<Poco::XML::CDATASection> pCDATA = pDoc->createCDATASection("sql=select * from table1 where id<5");

    pDoc->appendChild(pi);
    pDoc->appendChild(pComment);
    pDoc->appendChild(pRoot);
    pRoot->appendChild(pChild);
    pChild->appendChild(pGrandchild1);
    pChild->appendChild(pGrandchild2);
    pGrandchild1->appendChild(pNumOfPeople);
    pRoot->appendChild(pCDATA);

    Poco::XML::DOMWriter writer;
    writer.setOptions(Poco::XML::XMLWriter::PRETTY_PRINT);// PRETTY_PRINT = 4
    writer.writeNode("./example.xml", pDoc);//直接写进文件
    //或者直接写进string
    std::stringstream sstr;
    writer.writeNode(sstr, pDoc);
    std::string s = sstr.str();

    return 0;
}

 2. 解析xml   (注意:只能对 Poco::XML::Document 使用智能指针 AutoPtr,或者delete,否则出现多次析构错误)

所以,除了Document的指针,其他Node,Attr什么的千万别用智能指针。

引用:https://blog.csdn.net/qq_30811835/article/details/81939392

//解析xml
    std::string strXml = "<?xml version="1.0" encoding="utf-8" ?><!--this is a comment.--><books><book category = "children" language = "English" name = "123English"><title>Harry Potter</title><author>J.K. Rowling</author><price>29.99</price></book><function><![CDATA[bool cmp(int a, int b)    {return a<b;}]]></function></books>";

    Poco::XML::DOMParser parser;
    //parser.setFeature(Poco::XML::DOMParser::FEATURE_FILTER_WHITESPACE, true);//过滤空白符
    //Poco::AutoPtr<Poco::XML::Document> pDoc = parser.parse("./example.xml");//解析xml文件
    Poco::AutoPtr<Poco::XML::Document> pDoc = parser.parseString(strXml);//解析xml字符串
    
//获取特定name的元素
    
    //Poco::AutoPtr<Poco::XML::Node> pNode = pDoc->firstChild();//出错!!别用智能指针
    Poco::XML::Node* pNode = pDoc->firstChild();//正确
    //通过Path获取元素
    Poco::XML::Element* elem = (Poco::XML::Element*)(pDoc->getNodeByPath("books/book"));//同样别用智能指针
    std::string s1 = elem->getAttribute("language");//"English"
    std::string s2 = elem->getAttribute("category");//"children"
    std::string s3 = elem->getChildElement("author")->innerText();//J.K. Rowling
    std::string s4 = elem->getChildElement("price")->innerText();//29.99
    std::string s5 = elem->getNodeByPath("title")->innerText();//Harry Potter
#include <Poco/AutoPtr.h>            //fro Poco::AutoPtr
#include <Poco/DOM/Document.h>        //for Poco::XML::Document
#include <Poco/DOM/DOMParser.h>        //for Poco::XML::DOMParser
#include <Poco/DOM/NodeIterator.h>    //for Poco::XML::NodeIterator
#include <Poco/DOM/NodeFilter.h>    //for Poco::XML::NodeFilter
#include <Poco/DOM/Node.h>            //for Poco::XML::Node
#include <Poco/DOM/NamedNodeMap.h>    //for Poco::XML::NamedNodeMap
int main(int argc, char** argv)
{
    //解析xml
    Poco::XML::DOMParser parser;
    //parser.setFeature(Poco::XML::DOMParser::FEATURE_FILTER_WHITESPACE, true);//过滤空白符
    Poco::AutoPtr<Poco::XML::Document> pDoc = parser.parse("./example.xml");//解析xml文件
    //Poco::AutoPtr<Poco::XML::Document> pDoc = parser.parseString(strXml);//解析xml字符串
    Poco::XML::NodeIterator it(pDoc, Poco::XML::NodeFilter::SHOW_ALL);//可以过滤 SHOW_ELEMENT SHOW_ATTRIBUTE  SHOW_TEXT  SHOW_CDATA_SECTION 等
    Poco::XML::Node* pNode = it.nextNode();
    while (pNode)
    {
        //if (pNode->nodeType() != Poco::XML::Node::ELEMENT_NODE)//过滤 非element
        //    {pNode = it.nextNode(); continue;}
        std::string sName = pNode->nodeName();
        std::string sValue = pNode->nodeValue();
        std::string sText = pNode->innerText();
        Poco::XML::NamedNodeMap* map = pNode->attributes();
        if (map)
        {
            for (int i = 0; i < map->length(); ++i)
            {
                Poco::XML::Node* attr = map->item(i);
                std::string sAttrName = attr->nodeName();
                std::string sAttrValue = attr->nodeValue();
                //...
            }
        }
        pNode = it.nextNode();
    }
    return 0;
}
节点 nodeName nodeValue
Document "#document" ""
Comment "#comment" ""
Element tag名 ""
Text "#text" 文本字符串
CDATASection "#cdata-section" CDATA内容
     

 

任何元素都被抽象成Node,同时又分为三种类型的节点。(Attr和Notation看成一种)
第一种类型:CharacterData,这类Node是Name不可变,而Value可以由用户自定义。
第二种类型:AbstractContainerNode,这类Node有个特点,即含有属性,特别的对于Element节点,Name可以由用户自定义,而Value不可变。
第三种类型:右边两个,它们既可以改变Name,也可以改变Value。
————————————————
原文链接:https://blog.csdn.net/ma52103231/article/details/7701880

SAM(The Simple API for XML)方式:

  参考官方文档:https://pocoproject.org/slides/170-XML.pdf

二、tinyXml

 下载https://sourceforge.net/projects/tinyxml/

解压缩tinyXML后,将这六个文件添加到你的C++工程中,分别是tinystr.h、tinystr.cpp、tinyxml.h、tinyxml.cpp、tinyxmlerror.cpp、tinyxmlparser.cpp。在需要操作xml文件的地方,使用如下代码,就可以引入TinyXML类库。 #include<tinyxml> 或 #include "tinyxml.h"

读xml:

try
{
    //TiXmlDocument *myDocument = new TiXmlDocument(fullPath.c_str());//这样最后要delete myDocument
    //myDocument->LoadFile();

    TiXmlDocument doc;
    //doc.LoadFile("info.xml");
    string str("<Persons>
                       <Person ID = '1' other = 'info'>
                        <name>Michael</name>
                        <age>23</age>
                    </Person>
                </Persons>");
    doc.Parse(str.c_str());//解析xml字符串
    TiXmlElement *RootElement = doc.RootElement();
    string root = RootElement->Value();
    TiXmlElement *FirstPerson = RootElement->FirstChildElement();
    TiXmlElement *NameElement = FirstPerson->FirstChildElement();
    TiXmlElement *AgeElement = NameElement->NextSiblingElement();
    TiXmlAttribute *IDAttribute = FirstPerson->FirstAttribute();
    string name = NameElement->FirstChild()->Value();//或NameElement->GetText()
    string age = AgeElement->FirstChild()->Value();//或AgeElement->GetText()
    string attrName = IDAttribute->Name();   //"ID"
    string attrValue = IDAttribute->Value(); //"1"
    attrName = IDAttribute->Next()->Name();  //"other"
    attrValue = IDAttribute->Next()->Value();//"info"
    //delete myDocument;
}
catch (string& e)
{
    return false;
}
return true;
View Code

写xml:

    try
    {
        TiXmlDocument *myDocument = new TiXmlDocument();
        TiXmlElement *RootElement = new TiXmlElement("Persons");
        myDocument->LinkEndChild(RootElement);
        TiXmlElement *PersonElement = new TiXmlElement("Person");
        RootElement->LinkEndChild(PersonElement);
        PersonElement->SetAttribute("ID", "1");
        PersonElement->SetAttribute("other", "info");
        TiXmlElement *NameElement = new TiXmlElement("name");
        TiXmlElement *AgeElement = new TiXmlElement("age");
        PersonElement->LinkEndChild(NameElement);
        PersonElement->LinkEndChild(AgeElement);
        TiXmlText *NameContent = new TiXmlText("Michael");
        TiXmlText *AgeContent = new TiXmlText("23");
        NameElement->LinkEndChild(NameContent);
        AgeElement->LinkEndChild(AgeContent);
        CString appPath = GetAppPath();
        string seperator = "\";
        string fullPath = appPath.GetBuffer(0) + seperator + szFileName;
        myDocument->SaveFile(fullPath.c_str());
        delete myDocument;
    }
    catch (string& e)
    {
        return false;
    }
    return true;
View Code

读写xml

		<?xml version="1.0" encoding="utf-8" ?>
		<!--this is a comment.-->
		<books>
			<book category="children" language="English" name="123English">
				<title>Harry Potter</title>
				<anthor>J.K. Rowling</anthor>
				<price>29.99</price>
			</book>
			<function>
				<![CDATA[bool cmp(int a,int b)
		{return a<b;}]]>
			</function>
		</books>
        try
    {
        TiXmlDocument* doc = new TiXmlDocument;
        TiXmlDeclaration* decl = new TiXmlDeclaration("1.0", "utf-8", "");
        doc->LinkEndChild(decl);
        TiXmlComment* pComment = new TiXmlComment("this is a comment.");
        doc->LinkEndChild(pComment);

        TiXmlElement *root, *elem, *child;
        TiXmlText *text;
        root = new TiXmlElement("books");
        doc->LinkEndChild(root);

        elem = new TiXmlElement("book");
        elem->SetAttribute("category", "children");
        elem->SetAttribute("language", "English");
        elem->SetAttribute("name", "123English");//可以解出来123,但“English123”不能
        root->LinkEndChild(elem);
        child = new TiXmlElement("title");
        text = new TiXmlText("Harry Potter");
        child->LinkEndChild(text);
        elem->LinkEndChild(child);
        child = new TiXmlElement("anthor");
        text = new TiXmlText("J.K. Rowling");
        child->LinkEndChild(text);
        elem->LinkEndChild(child);
        child = new TiXmlElement("price");
        text = new TiXmlText("29.99");
        child->LinkEndChild(text);
        elem->LinkEndChild(child);

        //一个CDATA(Tixml看做是TiXmlText)
        elem = new TiXmlElement("function");
        TiXmlText* pCDATA = new TiXmlText("bool cmp(int a,int b)
{return a<b;}");
        pCDATA->SetCDATA(true);
        elem->LinkEndChild(pCDATA);
        root->LinkEndChild(elem);

        //doc->Print();//打印到 stdout cout
        doc->SaveFile("D:\test.xml");//输出到文件

        TiXmlPrinter printer;
        //printer.SetStreamPrinting();//有这句,无空白符,就一行字符串
        doc->Accept(&printer);
        string sRet = printer.CStr();//输出到字符串

        delete doc;//只需要这一个delete,它的所有子节点都delete了

        {//解析
            string sXml = sRet;
            TiXmlDocument doc;
            ////解析xml字符串
            //doc.Parse(sXml.c_str());
            //if (doc.Error())
            //    return false;
            //解析xml文件
            if (!doc.LoadFile("D:\test.xml"))
                return false;
            TiXmlElement* root = doc.RootElement();
            TiXmlElement* elem = root->FirstChildElement();
            //遍历
            for (TiXmlElement* tmp = elem->FirstChildElement(); tmp; tmp = tmp->NextSiblingElement())
            {
                string s = tmp->Value();
                const char* p = tmp->GetText();
                string t(p ? p : "");
            }
            //查找特定name的元素
            TiXmlElement* elem2 = root->FirstChildElement("book");
            //遍历Attribute
            for (TiXmlAttribute* pAttr = elem2->FirstAttribute(); pAttr; pAttr = pAttr->Next())
            {
                string sName = pAttr->Name();
                string sValue = pAttr->Value();
            }
            //获取特定attribute
            const char* psz1 = elem2->Attribute("language");//"English"
            const char* psz2 = elem2->Attribute("category");//"children",若没有找到"category"属性,则返回NULL
            //还有,直接取值的
            int i;
            elem2->Attribute("name", &i);//返回const char* , 失败返回NULL
            double d;
            elem2->Attribute("name", &d);
            elem2->QueryIntAttribute("name", &i);
            elem2->QueryDoubleAttribute("name", &d);
            bool b;
            elem2->QueryBoolAttribute("name", &b);
            //...

            //获取CDATA
            TiXmlElement* elem3 = root->FirstChildElement("function");
            string ss = elem3->GetText();
            string ss2 = elem3->FirstChild()->Value();//或者
        }
    }
    catch (std::string& e)
    {
        return false;
    }    
View Code

www.cnblogs.com/phinecos/archive/2008/03/11/1100912.html
www.cnblogs.com/MakeView660/p/6038173.html

三、CMarkup

官网下载地址:http://www.firstobject.com/dn_markup.htm 
网盘链接:https://pan.baidu.com/s/1VP-eo-SWkKChC6dhMmTakA   提取码:36pg

直接将 Markup.h 和 Markup.cpp 包含到工程中就可以使用了。

生成:

// VS2013,新建win32 console 空程序,添加Markup.h和Markup.cpp , 并设置工程属性,设置 MFC的使用: 在共享DLL中使用MFC
#include "Markup.h"
int main()
{
    CMarkup xml;
    xml.AddElem(_T("ORDER"));
    xml.AddChildElem(_T("ITEM"));
    xml.IntoElem();
    xml.AddChildElem(_T("SN"), _T("132487A-J"));
    xml.AddChildElem(_T("NAME"), _T("crank casing"));
    xml.AddChildElem(_T("QTY"), _T("1"));
    xml.OutOfElem();
    xml.AddChildElem(_T("PERSON"));
    xml.IntoElem();
    xml.SetAttrib(_T("name"), _T("Lee"));
    CString csXML = xml.GetDoc();
    xml.Save(_T("test.xml"));
    return 0;
}
/*结果
<ORDER>
<ITEM>
<SN>132487A-J</SN>
<NAME>crank casing</NAME>
<QTY>1</QTY>
</ITEM>
<PERSON name="Lee"/>
</ORDER>
*/

 解析xml:

// VS2013 , 属性设置 MFC的使用: 在共享DLL中使用MFC
#include "Markup.h"
#include <map>
#include <utility>      // std::pair
using std::map;
using std::pair;
int main()
{
    //CMarkup xml;
    //xml.AddElem(_T("ORDER"));
    //xml.AddChildElem(_T("ITEM"));
    //xml.IntoElem();
    //xml.AddChildElem(_T("SN"), _T("132487A-J"));
    //xml.AddChildElem(_T("NAME"), _T("crank casing"));
    //xml.AddChildElem(_T("QTY"), _T("1"));
    //xml.OutOfElem();
    //xml.AddChildElem(_T("PERSON"));
    //xml.IntoElem();
    //xml.SetAttrib(_T("name"), _T("Lee"));
    //CString csXML = xml.GetDoc();
    //xml.Save(_T("test.xml"));

    CMarkup xml;
    xml.Load(_T("test.xml"));
    //xml.SetDoc(strXML);//加载字符串xml
    //查找特定元素
    while (xml.FindChildElem(_T("ITEM")))
    {
        xml.IntoElem();
        xml.FindChildElem(_T("SN"));
        CString csSN = xml.GetChildData();
        xml.FindChildElem(_T("QTY"));
        int nQty = _ttoi(xml.GetChildData());
        xml.OutOfElem();
    }
    
    xml.ResetPos(); // top of document
    xml.FindElem(); // ORDER element is root
    xml.IntoElem();
    xml.FindElem();// ITEM element
    xml.IntoElem();
    map<CString, CString> mapData;
    while (xml.FindElem())
    {
        CString strName = xml.GetTagName();
        CString strData = xml.GetData();
        mapData.insert(std::make_pair(strName, strData));
        //mapData[strName] = strData;
    }
    return 0;
}

https://blog.csdn.net/wangshubo1989/article/details/52921285

引用:https://blog.csdn.net/jonathandj/article/details/4320725

最近正在研究C++下的XML分析工具CMarkup。初次和XML相遇是基于C#对XML的操作。C#的XmlDocument和XmlNode给我印象之深,让我至今都无法忘怀。现在想在C++下发掘XML的强大,结果却发现建房子你除了需要基本的建设材料外,还需要些而外的工具。不像C#那样,已经打成包供你直接使用了。好在有知道CMarkup这个小型XML的分析器,可以为我所用。俗话说:磨刀不误砍柴工。我现在就来磨下刀。
1、初始化
Load 导入一个XML文件到CMarkup的对象中,并对它进行解析。类似C#的Load。
SetDoc 从字符串中导入XML数据,并对它解析。类似C#的LoadXml。

2、输出
Save 将XML数据写入文件中。类似C#的Save。
GetDoc 将整个XML数据文档作为字符串返回。

3、改变当前位置
FindElem 定位到下一个元素,可能和一个标签名或路径匹配。
FindChildElem 定位到下一个子元素,匹配元素名或路径。
FindPrevElem 定位前一个元素,可能和一个标签名或路径匹配。
FindPrevChildElem 定位前一个子元素,可能匹配标签名。
FindNode  定位下一个节点,可能和节点类型匹配。
IntoElem  进入当前主位置的下一级,当前的位置变为父位置。
OutOfElem 使当前父位置变成当前位置。
ResetPos 复位当前位置为文档起始位置。
ResetMainPos 将当前主位置复位为第一个兄弟位置之前。
ResetChildPos 复位当前子位置到第一个子位置之前。
4、文档新增
AddElem 在当前主位置元素或最后兄弟位置之后增加一个元素。
InsertElem 在当前主位置元素或第一个兄弟位置之前插入一个元素。
AddChildElem 在当前子位置元素或最后一个子位置之后增加一个元素。
InsertChileElem 在当前子位置元素或低一个子位置之前插入一个元素。
AddSubDoc 在当前主位置元素或最后一个兄弟位置之后增加一个子文档。
InsertSubDoc 在当前主位置元素或第一个兄弟位置之前插入一个子文档。
AddChildSubDoc 在当前子位置元素或最后一个子位置之后增加子文档。
InsertChildSubDoc 在当前子位置元素或第一个子位置之前插入一个子文档。
AddNode 在当前节点之后或父元素内容末尾增加一个节点。
InsertNode 在当前节点之前或父元素内容开头插入一个节点。
5、文档中删除
RemoveElem 删除当前包括子元素的主位置元素
RemoveChildElem 删除包括当前子元素及其子元素
RemoveNode 删除当前节点
RemoveAttrib 删除当前位置元素具体的属性
RemoveChildAttrib 删除当前子位置元素的某个具体属性
6、得到值
GetData 得到当前主位置元素或节点的字符串值
GetChildData 得到当前子位置元素的字符串值
GetElemContent 得到当前主位置元素包括其子元素的标记内容字符串值
GetSubDoc 得到当前主位置元素包括其子元素的文档片断标记字符串值
GetChildSubDoc 得到当前子位置元素包括其子元素的文档片断标记字符串值
GetAttrib 得到主位置元素(或正在进行的指令的)某一具体属性字符串值
GetChildAttrib 得到子位置某一特定属性的字符串值
GetTagName 得到主位置元素(或正在进行的指令的)标签名称
GetChildTagName 得到子位置元素的标签名称
FindGetData 定位到匹配某一具体路径的下一个元素并返回字符串值
7、设置值
SetData 设置当前主位置元素或节点的值
SetChildData 设置当前子位置元素的值
SetElemContent 设置当前主位置元素的标记内容
SetAttrib 设置当前主位置元素(或正在进行的指令的)某一具体属性的值
SetChildAttrib 设置当前子位置元素某一具体属性的值
FindSetData 定位匹配某一具体路径的下一个元素并设置其值
8、获取其他信息
GetAttribName 当过当前位置元素属性的具体索引得到属性名称
GetNodeType 得到当前节点的节点类型
GetElemLevel 得到当前主位置的级数
GetElemFlags 得到当前主位置元素的标志
SetElemFlags 设置当前主位置元素的标志
GetOffsets 获得在当前主位置偏移的文档文本
GetAttribOffsets 获得在当前主位置特定属性便宜的文档文本
9、保存位置信息
SavePos 在hash map中使用可选字符串名称保存当前位置
RestorePos 定位到通过SavePos保存的位置
SetMapSize 设置SavePos和RestorePos使用的hash map大小
GetElemIndex 得到当前主位置元素整形索引值
GotoElemIndex 设置当前主位置元素为给定的整形索引值
GetChildElemIndex 得到当前子位置元素的整形索引值
GotoChildElemIndex 设置当前子位置元素为给定的整形索引值
GetParentElemIndex 获得当前父位置元素的整形索引值
GotoParentElemIndex 设置当前父位置元素为给定的整形索引值
GetElemPath 获得表示主位置元素绝对路径的字符串
GetChildElemPath 获得表示子位置元素的绝对路径的字符串
GetParentElemPath 获得表示父位置元素的绝对路径的字符串
10、文档状态
IsWellFormed 判定文档是否有单一根元素和恰当地包含元素
GetError 从最后的解析中返回错误(信息)字符串
GetDocFlags 返回文档标志
SetDocFlags 设置文档标志
GetDocElemCount 返回文档中元素的个数
11、静态的实用函数
ReadTextFile 读一个文本文件转成字符串
WirteTextFile 写字符串到文本文件中
GetDeclareEncoding 从XML声明中得到编码的名字
EscapeText 返回标记中某一字符的编码
UnescapeText 返回字符串值得某一特定字符解码
UTF8ToA 将UTF-8字符转成非Unicode(如ANSI)字符
AToUTF8 将非Unicode(如ANSI)字符转成UTF-8字符
UTF16T08 将UTF-16字符转成UTF-8
UTF8To16 将UTF-8字符转成UTF-16
EncodeBase64 将二进制数据译成Base64字符串
DecodeBase64 将Base64字符译成二进制数据

blog.csdn.net/weixin_33901926/article/details/89717752

Model

------------------------------------------------------------------------------------------

微软的MSXML

使用方法:
#import "C:\WINDOWS\system32\msxml6.dll"
//using namespace MSXML2;

例子:

xml是 <Book category="children"><title lang="en">Harry Potter</title><author>J.K. Rowling</author><year>2005</year><price>29.89</price></Book>

<Book category="children">
  <title lang="en">Harry Potter</title>
  <author>J.K. Rowling</author>
  <year>2005</year>
  <price>29.89</price>
</Book>
#import "C:\WINDOWS\system32\msxml6.dll"
//using namespace MSXML2;
void CtestDialogDlg::OnOK()
{
    {//创建xml文件
        ::CoInitialize(NULL);  //初始化COM
        MSXML2::IXMLDOMDocumentPtr pDoc;
        MSXML2::IXMLDOMElementPtr xmlRoot;
        HRESULT hr = pDoc.CreateInstance(__uuidof(MSXML2::DOMDocument30));
        if (!SUCCEEDED(hr))
        {
            MessageBox(L"XML文件创建失败");
            return;
        }

        pDoc->raw_createElement((_bstr_t)(char*)"Book", &xmlRoot);
        xmlRoot->setAttribute("category", "children");
        pDoc->raw_appendChild(xmlRoot, NULL);

        MSXML2::IXMLDOMElementPtr pElemNode;
        pDoc->raw_createElement((_bstr_t)(char*)"title", &pElemNode);
        pElemNode->Puttext("Harry Potter");
        pElemNode->setAttribute("lang", "en");
        xmlRoot->appendChild(pElemNode);

        pDoc->raw_createElement((_bstr_t)(char*)"author", &pElemNode);
        pElemNode->Puttext("J.K. Rowling");
        xmlRoot->appendChild(pElemNode);

        pDoc->raw_createElement((_bstr_t)(char*)"year", &pElemNode);
        pElemNode->Puttext("2005");
        xmlRoot->appendChild(pElemNode);

        pDoc->raw_createElement((_bstr_t)(char*)"price", &pElemNode);
        pElemNode->Puttext("29.89");
        xmlRoot->appendChild(pElemNode);

        pDoc->save(".\test.xml");//保存到文件
        //如何释放pDoc占有的内存
        ::CoUninitialize();  //卸载COM
    }

    {//读取xml文件
        ::CoInitialize(NULL);  //初始化COM
        m_list.DeleteAllItems();  //m_list是ListControl控件绑定的一个Value类型的变量
        MSXML2::IXMLDOMDocumentPtr pDoc;  //创建一个xml文档指针
        HRESULT hr = pDoc.CreateInstance(__uuidof(MSXML2::DOMDocument30));  //实例化文档指针
        if (!SUCCEEDED(hr))
        {
            MessageBox(L"加载XML错误");
            return;
        }
        VARIANT_BOOL loadrs = pDoc->load(".\test.xml");  //加载xml文档
        if (-1 != loadrs)  //load返回类型是VARIANT_BOOL,-1 == TRUE、0 == FALSE
            MessageBox(L"加载XML错误");
        MSXML2::IXMLDOMElementPtr pElemNode;  //声明一个元素(Element)指针

        // 在树中查找名为***的节点," // "表示在任意一层查找
        //selectSingleNode方法如果查询到一个或多个节点,返回第一个节点;如果没有查询的任何节点返回 Nothing
        //SelectNodes("//Book")返回一个NodeList对象,可能包含多个节点
        pElemNode = (MSXML2::IXMLDOMElementPtr)(pDoc->selectSingleNode("//Book"));  //获取元素的信息
        CString strValue = pElemNode->Gettext();//获取Element标签之间的Text文本,Puttext(LPCSTR)为设置Text文本
        //注意:Book的text是“Harry PotterJ.K. Rowling200529.89”

        CString strAttr = pElemNode->getAttribute("category");//获取元素的属性,若无这个属性抛异常

        //遍历子节点
        MSXML2::IXMLDOMNodeListPtr nodeList = NULL;
        pElemNode->get_childNodes(&nodeList);  //获取所有子节点
        long nCount = 0;
        nodeList->get_length(&nCount);
        MSXML2::IXMLDOMNodePtr pCurNode;
        for (int i = 0; i < nCount; ++i)
        {
            pCurNode = nodeList->nextNode();
            CString strName = pCurNode->GetnodeName();
            CString strValue = pCurNode->Gettext();
        }

        {
            //查询某个元素节点
            MSXML2::IXMLDOMNodePtr pNode;
            pNode = pDoc->selectSingleNode("Book/price");
            CString strValue = pNode->Gettext();
            pNode = pDoc->selectSingleNode("Book/title/@lang");//属性节点
            CString strAttrName = pNode->GetnodeName();//lang
            CString strAttrVal = pNode->GetnodeValue();//en
            pNode = pDoc->selectSingleNode("Book/title");
            strAttrVal = ((MSXML2::IXMLDOMElementPtr)pNode)->getAttribute("lang");//en
        }

        ::CoUninitialize();  //卸载COM
}
View Code

若解析xml字符串,则:

        const char* szXml = "<Book category="children"><title lang="en">Harry Potter</title><author>J.K. Rowling</author><year>2005</year><price>29.89</price></Book>";
        VARIANT_BOOL loadrs = pDoc->loadXML(szXml);

参考:
https://blog.csdn.net/qq2399431200/article/details/17583171
https://blog.csdn.net/sky786905664/article/details/53696076

----------------------------------------------------------------------------------

常记溪亭日暮,沉醉不知归路。兴尽晚回舟,误入藕花深处。争渡,争渡,惊起一滩鸥鹭。

昨夜雨疏风骤,浓睡不消残酒。试问卷帘人,却道海棠依旧。知否?知否?应是绿肥红瘦。
原文地址:https://www.cnblogs.com/htj10/p/11589357.html