笑看风云淡

宠辱不惊,看庭前花开花落;去留无意,望天空云卷云舒
posts - 96, comments - 48, trackbacks - 0, articles - 0
  C++博客 :: 首页 :: 新随笔 ::  :: 聚合  :: 管理

使用MSXML在VC++中解析XML文件

Posted on 2009-08-25 15:29 天之骄子 阅读(5061) 评论(0)  编辑 收藏 引用

好久没有在VC++里面解析XML了,昨天遇到一个问题,从昨天下午一直到今天上午,差不多搞了一天,才终于把问题解决了。
使用MSXML在VC++中解析XML文件时候,只需要做到下面几点:
1、初始化COM库,CoInitialize(NULL);可以放在InitInstance()函数里面。释放COM库,CoUninitialize();可以放在ExitInstance()函数里面。
2、在头文件里面加入如下代码

#import "MSXML6.dll" rename_namespace("MSXML6") named_guids
using namespace MSXML6;
因为解析的时候要用到CComVariant类,所以还要加上
#include <atlbase.h>
3、解析XML文件。
需要解析的XML文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<SCL xmlns="http://www.iec.ch/61850/2003/SCL">
    
<Address type="MAC-Address" xsi:type="tP_MAC-Address">
    01-0C-CD-01-00-08
</Address>
</SCL>
首先要加载XML文件,代码如下:
    HRESULT hr;
    IXMLDOMDocument 
*pDoc=NULL;

    CString strFileName;
    
    CFileDialog fileDlg(TRUE);
    fileDlg.m_ofn.lpstrTitle
="打开XML文件";
    fileDlg.m_ofn.lpstrFilter
="XML Files(*.xml)\0*.xml\0All Files(*.*)\0*.*\0\0";
    fileDlg.m_ofn.lpstrDefExt
="xml";
    
if(fileDlg.DoModal() != IDOK)
        
return;
    strFileName
=fileDlg.GetPathName();        //获得要解析的XML文件的路径名
    ASSERT(!strFileName.IsEmpty());

    
if(SUCCEEDED(CoCreateInstance(CLSID_DOMDocument,NULL,
        CLSCTX_INPROC_SERVER,IID_IXMLDOMDocument,(
void**)&pDoc)))    //创建Document对象
    {
        CComVariant vPath(strFileName);
        VARIANT_BOOL isSuccessful;
        pDoc
->raw_load(vPath,&isSuccessful);    //加载要解析的XML文件
        if(isSuccessful!=VARIANT_TRUE)
        
{
            AfxMessageBox(
"wrong!");
            
return;
        }

    }
我当时在加载XML文件的时候老是报错,本来以为是代码的问题,找了半天都没问题呀。后来发现XML文件的问题,问题出在xsi:type上,如果将xsi:type改成别的(比如ype就可以了);或者是在根元素里面定义好xsi的意义,修改后的XML文件如下
<?xml version="1.0" encoding="UTF-8"?>
<SCL xmlns="http://www.iec.ch/61850/2003/SCL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    
<Address type="MAC-Address" xsi:type="tP_MAC-Address">
    01-0C-CD-01-00-08
</Address>
</SCL>
现在加载XML文件已经没有问题了,下面就是解析XML文件了。我所做的工作是得到元素Address的两个属性的名称type和xsi:type,以及它们的属性值。
我原来的解析代码是:
    IXMLDOMElement *pRootElement=NULL;
    IXMLDOMNode 
*pRootNode=NULL;

    IXMLDOMNamedNodeMap 
*pAttrMap=NULL;
    IXMLDOMNode 
*pAttrNode=NULL;
    IXMLDOMNode 
*pAddrNode=NULL;

    CString strName,strText;
    BSTR bsName,bsText;

    hr
=pDoc->get_documentElement(&pRootElement);
    
if(SUCCEEDED(hr) && (pRootElement!=NULL))
    
{
        hr
=pRootElement->QueryInterface(IID_IXMLDOMNode,(void**)&pRootNode);
        
if(SUCCEEDED(hr))
        
{

            hr
=pRootNode->get_firstChild(&pAddrNode);
            
if(SUCCEEDED(hr) && (pAddrNode!=NULL))
            
{
                pAddrNode
->get_attributes(&pAttrMap);
                
                
long length=0;
                pAttrMap
->get_length(&length);
                
for(int i=0;i<length;i++)
                
{
                    hr
=pAttrMap->get_item(i,&pAttrNode);
                    
if(SUCCEEDED(hr) && (pAttrNode!=NULL))
                    
{
                        pAttrNode
->get_baseName(&bsName);
                        pAttrNode
->get_text(&bsText);
                        strName
=bsName;
                        strText
=bsText;
                        
                        SysFreeString(bsName);
                        SysFreeString(bsText);
                    }

                }

            }

        }

    }
后来调试的时候发现,对xsi:type属性节点调用get_basename()方法,得到的是type,而不是xsi:type;当然对type属性节点调用get_basename()方法,得到的是type,这个正常。后来我改用IXMLDOMNode的get_nodeName()方法,才把问题解决了。对xsi:type属性节点调用get_nodename()方法,得到的是xsi:type;对type属性节点调用get_nodename()方法,得到的是type。
修改后的VC++代码如下
    IXMLDOMElement *pRootElement=NULL;
    IXMLDOMNode 
*pRootNode=NULL;

    IXMLDOMNamedNodeMap 
*pAttrMap=NULL;
    IXMLDOMNode 
*pAttrNode=NULL;
    IXMLDOMNode 
*pAddrNode=NULL;

    CString strName,strText;
    BSTR bsName,bsText;

    hr
=pDoc->get_documentElement(&pRootElement);
    
if(SUCCEEDED(hr) && (pRootElement!=NULL))
    
{
        hr
=pRootElement->QueryInterface(IID_IXMLDOMNode,(void**)&pRootNode);
        
if(SUCCEEDED(hr))
        
{

            hr
=pRootNode->get_firstChild(&pAddrNode);
            
if(SUCCEEDED(hr) && (pAddrNode!=NULL))
            
{
                pAddrNode
->get_attributes(&pAttrMap);
                
                
long length=0;
                pAttrMap
->get_length(&length);
                
for(int i=0;i<length;i++)
                
{
                    hr
=pAttrMap->get_item(i,&pAttrNode);
                    
if(SUCCEEDED(hr) && (pAttrNode!=NULL))
                    
{
                        pAttrNode
->get_nodeName(&bsName);
                        pAttrNode
->get_text(&bsText);
                        strName
=bsName;
                        strText
=bsText;
                        
                        SysFreeString(bsName);
                        SysFreeString(bsText);
                    }

                }

            }

        }

    }

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理