zoukankan      html  css  js  c++  java
  • vc中使用MSXML2的注意点

    MSXML2能够很好地处理xml文件,不过也有些需要注意的点

    1. MSXML2的加载和释放

       loadIndexXml(TCHAR * indexdir) {
    if (NULL == indexdir){
    return NULL;
    }
    ::CoInitialize(NULL);
    MSXML2::IXMLDOMDocumentPtr doc;
    doc.CreateInstance(__uuidof(DOMDocument60));
    if (VARIANT_FALSE == doc->load(indexdir)){
    doc.Release();
    return NULL;
    }

     ......do smthing();

    doc.Release();

    CoUninitialize();

     2. 新建一个xml文件

    CString setnameindex;
    setnameindex.Format("./xxx/%s.xml", name);
    //判断文件是否存在
    HANDLE hOpenFile = (HANDLE)CreateFile(setnameindex, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);
     
    if (hOpenFile == INVALID_HANDLE_VALUE) {
    ::CoInitialize(NULL);
    MSXML2::IXMLDOMDocumentPtr setnamedoc;
    setnamedoc.CreateInstance(__uuidof(DOMDocument60));
    char* dbfile = (LPSTR)(LPCSTR)setnameindex;
     
    setnamedoc->preserveWhiteSpace = VARIANT_TRUE;//这个必须设置,不然不生效
    MSXML2::IXMLDOMProcessingInstructionPtr pProInstruction = NULL;
    pProInstruction = setnamedoc->createProcessingInstruction((_bstr_t)(char*)"xml", (_bstr_t)(char*)"version="1.0" encoding="utf-8"");
    ((MSXML2::IXMLDOMNodePtr)setnamedoc)->appendChild(pProInstruction);
    MSXML2::IXMLDOMElementPtr pRootElement = NULL;
    pRootElement = setnamedoc->createElement((_bstr_t)(char*)"db");
    setnamedoc->PutRefdocumentElement(pRootElement);
    ((MSXML2::IXMLDOMNodePtr)setnamedoc->documentElement)->appendChild(setnamedoc->createTextNode(" "));
    MSXML2::IXMLDOMCommentPtr pComment = setnamedoc->createComment((_bstr_t)(char*)"db");
    ((MSXML2::IXMLDOMNodePtr)pRootElement)->appendChild(pComment); // 注释
    setnamedoc->save((LPSTR)(LPCSTR)setnameindex);
       setnamedoc.Release();
    //CoUninitialize();
    }

     3.获取某个节点列表,判断节点是否存在,并做处理

    MSXML2::IXMLDOMNodeListPtr node_person_list = ((MSXML2::IXMLDOMNodePtr)doc)->selectNodes("register/person");

    if (NULL == node_person_list || node_person_list->Getlength() == 0) {
    ........不存在的情况
    }

    else{

    ........存在的情况 

     xml文件:

    <register>

    <person name="xxxx" file="./a/b/c.png" date="0"/>

     <person name="xxxx" file="./a/b/c.png" date="0"/>

    .... 

    </register>

    4. 获取节点属性 如name file data

    MSXML2::IXMLDOMNodeListPtr node_person_list = ((MSXML2::IXMLDOMNodePtr)doc)->selectNodes("register/person");
    for (int i = 0; i < node_person_list->Getlength(); i++)
    {
    MSXML2::IXMLDOMNodePtr node_item = node_person_list->Getitem(i);
    _variant_t var_name = ((MSXML2::IXMLDOMElementPtr)node_item)->getAttribute("name");
    _variant_t var_file = ((MSXML2::IXMLDOMElementPtr)node_item)->getAttribute("file");
    _variant_t var_date = ((MSXML2::IXMLDOMElementPtr)node_item)->getAttribute("date");
    _variant_t var_score = NULL;
    var_score = ((MSXML2::IXMLDOMElementPtr)node_item)->getAttribute("score");
     
    n->name = _tcsdup(CString(var_name.bstrVal));
    //n->score = wcstol(var_score.bstrVal, NULL, 0);
    TCHAR temp[1024];
    //_tcscpy(temp, TEXT("facescore/woman/"));
    _tcscpy(temp, TEXT(""));
    _tcscat(temp, CString(var_file.bstrVal));
    n->file = _tcsdup(temp);
    //n->feature = (float *)malloc(sizeof(float) * 2048);
    n->date = _ttoi((LPCTSTR)(_bstr_t)var_date);
    if (var_score.vt != VT_NULL) {
    n->score = _ttoi((LPCTSTR)(_bstr_t)var_score);
    }
    else {
    n->score = -1;
    }
    }
    lw->AddTail(n);
    }

    其中 var_score取出来后,不知道判断是不是取到了正确的值,不能直接使用,错误使用会导致崩溃,判断的方法如下:

    if (var_score.vt != VT_NULL) {
    n->score = _ttoi((LPCTSTR)(_bstr_t)var_score);
    }

     5.删除某个节点,并保存

    CString dbxml;
    dbxml.Format("./xxx/%s.xml", name);
    ::CoInitialize(NULL);
    MSXML2::IXMLDOMDocumentPtr doc;
    doc.CreateInstance(__uuidof(DOMDocument60));
    if (VARIANT_FALSE == doc->load(((LPSTR)(LPCSTR)dbxml))) {
    doc.Release();
    return 2;
    }
    time_t t = time(nullptr);
    MSXML2::IXMLDOMNodePtr item;
    CString str;
    str.Format("db/item[@name='%s']", name);
    //_variant_t var(str);
    item = ((MSXML2::IXMLDOMNodePtr)doc)->selectSingleNode(_bstr_t(str));
    if (item != NULL) {
    item->GetparentNode()->removeChild(item);
    }
    doc->save((LPSTR)(LPCSTR)dbxml);
    doc.Release();
    CoUninitialize();

     6.更新xml里面某些节点的数据(先删除,再添加)

    str.Format("db/item[@name='%s']/features/feature", duq.name);
    //_variant_t var(str);
    feature = ((MSXML2::IXMLDOMNodePtr)doc)->selectSingleNode(_bstr_t(str));
    if (feature != NULL) {
    ((MSXML2::IXMLDOMElementPtr)feature)->setAttribute("date", t);
    MSXML2::IXMLDOMNodeList *pNodeList = NULL;
    feature->get_childNodes(&pNodeList);
    Debug_TraceA("UpdataSingleItemToDbXML get_childNodes ");
    if (pNodeList != NULL) {
    for (int i = 0; i < pNodeList->Getlength(); i++) {
    MSXML2::IXMLDOMNodePtr pNode;
    pNodeList->get_item(i, &pNode);
    feature->removeChild(pNode);
    }
    }
    for (int i = 0; i < feature_size; i++) {
    MSXML2::IXMLDOMNodePtr node_float = doc->createElement("f");
    CString s;
    s.Format("%.8f", userfeature[i]);
    _variant_t var(s);
    node_float->put_text(_bstr_t(s));
    //node_float->nodeValue.fltVal = p->feature[i];// CComVariant(p->feature[i]);
    feature->appendChild(node_float);
    }
    }
    doc->save(dbxml);
    doc.Release();
    CoUninitialize();

     7.msxml在save的时候报错,如果路径没问题,很有可能在别的地方有xml文件的引用没有释放,必须提前释放

        try {
        doc->save((LPSTR)(LPCSTR)dbxml);
        }
        catch (_com_error errorObject){
        Debug_TraceA("Exception, HRESULT = %d  %s 
    ", errorObject.Error(), (LPCTSTR)errorObject.Description());
        }

    可以通过上面代码查看异常

     
     
    msxml坑多浪急
            MSXML2::IXMLDOMNodeList *pNodeList = NULL;
            feature->get_childNodes(&pNodeList);
            
            if (pNodeList != NULL) {
                
                //Debug_TraceA("pNodeList->Getlength() %d  %d 
    ", pNodeList->Getlength(), feature->GetchildNodes()->length);
                //MSXML2::IXMLDOMNodePtr pNode;
                //while (pNode = pNodeList->nextNode() != NULL) {
                //    feature->removeChild(pNode);
                //}
                for (int i = pNodeList->Getlength()-1; i >=0; i--) {
                    MSXML2::IXMLDOMNodePtr pNode;
                    pNodeList->get_item(i, &pNode);
                    feature->removeChild(pNode);
                }
            }

    这是正常的代码

    这是错误的代码,因为pNodeListfeature是关联的,从前面removeChild,pNodeList->Getlength()的值在变小,每执行一次,任意一个子节点就向前移动一位,位置下标就减小1,而i是一直累加的所以会出问题

       MSXML2::IXMLDOMNodeList *pNodeList = NULL;
            feature->get_childNodes(&pNodeList);
            
            if (pNodeList != NULL) {
                
                //Debug_TraceA("pNodeList->Getlength() %d  %d 
    ", pNodeList->Getlength(), feature->GetchildNodes()->length);
          
                for (int i = 0; i <pNodeList->Getlength(); i++) {
                    MSXML2::IXMLDOMNodePtr pNode;
                    pNodeList->get_item(i, &pNode);
                    feature->removeChild(pNode);
                }
            }

     同理这个也是错的

            MSXML2::IXMLDOMNodeList *pNodeList = NULL;
            feature->get_childNodes(&pNodeList);
            
            if (pNodeList != NULL) {
                
                //Debug_TraceA("pNodeList->Getlength() %d  %d 
    ", pNodeList->Getlength(), feature->GetchildNodes()->length);
                MSXML2::IXMLDOMNodePtr pNode;
                while (pNode = pNodeList->nextNode() != NULL) {
                    feature->removeChild(pNode);
                }
    
            }
  • 相关阅读:
    STL容器内数据删除
    grep 同时满足多个关键字和满足任意关键字
    程序运行栈空间不足程序崩溃问题
    VS2010中设置程序以管理员身份运行
    python 包详解
    select 详解
    Hdu 1166
    CF1204C
    CF1204B
    CF1204A
  • 原文地址:https://www.cnblogs.com/baldermurphy/p/6233687.html
Copyright © 2011-2022 走看看