• [转载]C++中处理XML文件


     

     写Unmanaged Code.NET时代成为一种很悲惨的事,当你需要处理XML文件时,这种感觉会变得尤其强烈。FCL中的System.XML多简单啊,连Steve Ballmer都知道怎么用。 

    事情不会总是那么理想的,假如你要在C/C++程序里处理XML怎么办呢? 

    选择一:市面上的XML lib还是有几个的,最有名的当然是libXML。我一年前用过,很不错,我还特意写了一份简明教程,后来不知搁哪儿了。 

    选择二:MSMSXML,我要介绍的就是这个。 

    先说一下在MSDN哪里找文档吧,往下看的时候也好有个参考:在Index里打:Windows Media Services 9 Series SDK=>Programming Reference=>Programming Reference (C++)=>XML DOM Interfaces (C++)。什么?Windows Media?呵呵,不错,我觉得这个guide反而是最清楚的,你直接找MSXML,得到的结果,我觉得还没这个好。 

    C程序里调用MSXML基本就是一堆COM接口,不过在Visual Studio里操作先要做点简单的设置: 

    在你的ProjectAdd References=>COM标签=>Microsoft XML v4.05.0其实也有了,但因为是和Office一起发布的,觉得有点怪,不想用,反正也未必用什么很怪异的功能,4.0可以了。 



    然后在加入这两行: 

    #include <msXML2.h> 
    #import <msXML4.dll> 

    头文件和dll库。什么?在哪里加?头文件或者c/cpp文件啊,哪里合适放哪儿。 

    然后就开始编程了,先定义两个必用的变量: 

    IXMLDOMDocumentPtr XMLFile = NULL; 
    IXMLDOMElement* XMLRoot = NULL; 

    为什么是必用的?  汗... 

    第一步当然是初始化COM 

    if(FAILED(CoInitialize(NULL))) .... 

    接下来初始化XMLFile对象: 

    if(FAILED(XMLFile.CreateInstance("MsXML2.DOMDocument.4.0"))) ... 

    然后就可以加载XML文件了: 

    _variant_t varXML(L"C: est.XML"); //L for unicode 
    VARIANT_BOOL varOut; 
    XMLFile->load(varXML, &varOut); 

    取得root element 

    XMLFile->get_documentElement(&XMLRoot)) 

    取得第一级element 

    IXMLDOMNodeList* XMLChildNodes = NULL; 
    XMLRoot->get_childNodes(&XMLChildNodes); 

    遍历所有第一级element: 

    IXMLDOMNode* currentNode = NULL; 
    while(!FAILED(XMLChildNodes->nextNode(&currentNode)) && currentNode != NULL) 

    //do something 


    取得当前element的名称: 

    BSTR nodeName; 
    currentNode->get_nodeName(&nodeName); 

    取得当前element的一个attribute(假设这个attributetype)的值: 

    IXMLDOMNamedNodeMap* attributes = NULL; 
    IXMLDOMNode* attributeName = NULL; 
    _bstr_t bstrAttributeName = "type"; 
    BSTR nameVal; 
    currentNode->get_attributes(&attributes); 
    attributes->getNamedItem(bstrAttributeName, &attributeName); 
    attributeName->get_text(&nameVal); 

    需要注重的是,你要记住释放所有的借口,IXMLDOM***->Release(),这可不是.NET,有人帮你GC,你得自己调用Release()来减reference countit's COM, remember? 

    好了,大致就这样,顺便提一下XPath 

    _bstr_t bstrXMLQuery = L"/books/book[@type=scifi and @author=fox]"; 

    IXMLDOMNodeList* nodes = NULL; 
    if(FAILED(XMLRoot->selectNodes(bstrXMLQuery, &nodes)) FAILED(nodes->get_length(&length)) length == 0) 
    //no match found or something went wrong 
    else 
    //match found 

    上面是找这样的node: 

    <books> 
    <book type="scifi" author="fox">.... 
    </book> 
    .... 
    </books> 

    具体的XPath语法就查手册吧,到处都有。 

    哦,对了,忘了说:假如你全部用ATL的类的话,借口的调用会简单一点,不过很轻易转换的,比如: 

    IXMLDOMDocument*
    对应 IXMLDOMDocumentPtr(我这里用了),其他基本也是加个Ptr,我不废话了。 

    最后提供一个sample,我临时攒的。工作的时候写的程序当然不能拿来贴的,呵呵。这个sample基本就是遍历整个XML,然后报告一遍文件的结构,对每个node,假如它有一个叫idattribute,就同时打印id的值。If you want the complete VS project, shoot me an email. But I guess no one really needs it anyway, right, : ) 

    #include "stdafx.h" 
    #include <windows.h> 
    #include <msXML2.h> 
    #import <msXML4.dll> 

    HANDLE logFile = NULL; 

    #define INDENT 4 

    #define TESTHR(hr) 

    if(FAILED(hr)) goto fail; 


    void PrintChild(IXMLDOMNodeList* nodeList, int level) 

    if(nodeList == NULL) 
    return; 

    IXMLDOMNode* currentNode = NULL; 
    IXMLDOMNodeList* childNodes = NULL; 
    IXMLDOMNamedNodeMap* attributes = NULL; 
    IXMLDOMNode* attributeID = NULL; 

    while(!FAILED(nodeList->nextNode(&currentNode)) && currentNode != NULL) 

    BSTR nodeName; 
    TESTHR(currentNode->get_nodeName(&nodeName)); 
    DWord dwBytesWritten; 
    for(int i=0; i<level*INDENT; i++) 
    WriteFile(logFile, L" ", (Dword)(sizeof(WCHAR)), &dwBytesWritten, NULL); 

    //WCHAR msg[MAX_SIZE]; 
    //wsprintf(msg, L"%s ", nodeName); 
    WriteFile(logFile, nodeName, (Dword)(wcslen(nodeName)*sizeof(WCHAR)), &dwBytesWritten, NULL); 

    TESTHR(currentNode->get_attributes(&attributes)); 
    if(attributes!=NULL) 

    _bstr_t bstrAttributeName = "id"; 
    BSTR idVal; 
    TESTHR(attributes->getNamedItem(bstrAttributeName, &attributeID)); 
    if(attributeID != NULL) 

    TESTHR(attributeID->get_text(&idVal)); 
    WriteFile(logFile, L" ", (Dword)(sizeof(WCHAR)), &dwBytesWritten, NULL); 
    WriteFile(logFile, idVal, (Dword)(wcslen(idVal)*sizeof(WCHAR)), &dwBytesWritten, NULL); 
    WriteFile(logFile, L" ", (Dword)(2*sizeof(WCHAR)), &dwBytesWritten, NULL); 
    attributeID->Release(); attributeID = NULL; 

    else 

    WriteFile(logFile, L" ", (Dword)(2*sizeof(WCHAR)), &dwBytesWritten, NULL); 


    attributes->Release(); attributes = NULL; 


    else 

    WriteFile(logFile, L" ", (Dword)(2*sizeof(WCHAR)), &dwBytesWritten, NULL); 


    TESTHR(currentNode->get_childNodes(&childNodes)); 
    PrintChild(childNodes, level+1); 
    currentNode=NULL; 


    fail: 
    if(childNodes!=NULL) 
    childNodes->Release(); 
    if(attributeID!=NULL) 
    attributeID->Release(); 
    if(attributes!=NULL) 
    attributes->Release(); 
    if(currentNode != NULL) 
    currentNode->Release(); 


    int _tmain(int argc, _TCHAR* argv[]) 


    IXMLDOMDocumentPtr XMLFile = NULL; 
    IXMLDOMElement* XMLRoot = NULL; 
    _variant_t varXML(L"C:demo1.XML"); 

    logFile = CreateFile(L"log.txt", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 
    if(logFile == INVALID_HANDLE_VALUE) 
    goto fail; 

    TESTHR(CoInitialize(NULL)); 

    TESTHR(XMLFile.CreateInstance("MsXML2.DOMDocument.4.0")); 

    VARIANT_BOOL varOut; 
    TESTHR(XMLFile->load(varXML, &varOut)); 

    TESTHR(XMLFile->get_documentElement(&XMLRoot)); 

    BSTR rootName; 
    Dword dwBytesWritten; 
    TESTHR(XMLRoot->get_nodeName(&rootName)); 
    WriteFile(logFile, rootName, (Dword)(wcslen(rootName)*sizeof(WCHAR)), &dwBytesWritten, NULL); 
    WriteFile(logFile, L" ", (Dword)(2*sizeof(WCHAR)), &dwBytesWritten, NULL); 

    IXMLDOMNodeList* XMLChildNodes = NULL; 
    TESTHR(XMLRoot->get_childNodes(&XMLChildNodes)); 

    PrintChild(XMLChildNodes, 2); 

    fail: 
    if(logFile != INVALID_HANDLE_VALUE) 
    CloseHandle(logFile); 
    if(XMLChildNodes!=NULL) 
    XMLChildNodes->Release(); 
    if 
     

     

    原文来自 http://school.cnd8.com/c/jiaocheng/10145.htm

     

  • 相关阅读:
    python: 字符串按空格分成列表split与加密密码maketrans
    android 几个工具方法
    华硕N43sl VNP 连接问题 800 807 621
    git 创建新项目,下载工程,合并和更新工程简单应用记录
    android分析windowManager、window、viewGroup之间关系(二)
    android分析windowManager、window、viewGroup之间关系(一)
    meta-data获取小结
    转载: 项目经验分享
    不想写代码了
    MapReduce源码分析总结(转)
  • 原文地址:https://www.cnblogs.com/time-is-life/p/5671872.html
Copyright © 2020-2023  润新知