VC++ 读取xml文件包含中文就出错,如何才能支持中文(宽字符)

时间:2022-04-16 11:54:42
xml文件格式及内容如下:

<Buttons>
    <Button id="101">One</Button>
    <Button id="102">Two</Button>
    <Button id="103">Three</Button>
    <Button id="104">我的联系人</Button>
</Buttons>


加载文件代码:

//加载  竟然不支持“宽字符”
VARIANT_BOOL loadrs = pDoc->load(".\\DirectBtnsInfo.xml");  //加载xml文档
    if( -1 != loadrs )  // -1表示加载成功
return FALSE;

    返回值loadrs竟然为0,如果加载正常返回值应该是-1。于是我将xml文件中含中文的那行删除后再次加载正常。不知道是为什么,难道VC++不支持对宽字符的读写?
    请帮我解决下这个问题,谢谢。

15 个解决方案

#1


中文的问题?lz试下这个,在接口初始化之前调用:setlocale(LC_ALL,"chs");
完成之后再调用setlocale设置回原来的模式

#2


引用 1 楼 sd__q 的回复:
中文的问题?lz试下这个,在接口初始化之前调用:setlocale(LC_ALL,"chs");
完成之后再调用setlocale设置回原来的模式



setlocale(LC_ALL,"chs");  //设置语言环境 包含<locale.h>
::CoInitialize(NULL);  //初始化COM
MSXML2::IXMLDOMDocumentPtr pDoc;  //创建一个xml文档指针
HRESULT hr = pDoc.CreateInstance(__uuidof(MSXML2::DOMDocument30));  //实例化文档指针
if(!SUCCEEDED(hr))
{
MessageBox("初始化错误");
return FALSE;
}

//加载  竟然不支持“宽字符”
VARIANT_BOOL loadrs = pDoc->load(".\\DirectBtnsInfo.xml");  //加载xml文档
    if( -1 != loadrs )  // -1表示加载成功
return FALSE;

//省略xml文档读取操作代码

setlocale(LC_ALL,"english");
::CoUninitialize();  //卸载COM


设置本地语言环境后,在调用load函数后返回来的值依然是加载失败!

#3


引用 1 楼 sd__q 的回复:
中文的问题?lz试下这个,在接口初始化之前调用:setlocale(LC_ALL,"chs");
完成之后再调用setlocale设置回原来的模式


谢谢阁下的解答,问题已经解决。问题出在xml文件中--缺少xml文件头标签:
<?xml version="1.0" encoding="gb2312"?>

并且COM接口初始化前也不需要调用setlocale函数设置本地语言(可能我的操作系统是中文版的缘故)。

#4


引用 3 楼 qq2399431200 的回复:
Quote: 引用 1 楼 sd__q 的回复:

中文的问题?lz试下这个,在接口初始化之前调用:setlocale(LC_ALL,"chs");
完成之后再调用setlocale设置回原来的模式


谢谢阁下的解答,问题已经解决。问题出在xml文件中--缺少xml文件头标签:
<?xml version="1.0" encoding="gb2312"?>

并且COM接口初始化前也不需要调用setlocale函数设置本地语言(可能我的操作系统是中文版的缘故)。

奥,之前整过一个基于gsoap webservice相关的,也需要解析xml,宽字节中文乱码设置这个就可以了

#5


xml有专用的解析类,用起来方便

#6


CMarkUp用起来更方便

#7


引用 6 楼 sunnyloves 的回复:
CMarkUp用起来更方便

好用是不用怀疑的,但是解决问题就不要逃避这个问题,虽然用它能达到这个效果。

#8


引用 5 楼 GLSC_CENA 的回复:
xml有专用的解析类,用起来方便

吊胃口么?帮忙就要力所能及,如果只有只言片语又不能实实在在帮到别人,还不如帮顶来得实在。

#9


引用 8 楼 qq2399431200 的回复:
Quote: 引用 5 楼 GLSC_CENA 的回复:

xml有专用的解析类,用起来方便

吊胃口么?帮忙就要力所能及,如果只有只言片语又不能实实在在帮到别人,还不如帮顶来得实在。


http://www.baidu.com/s?wd=vc+xml+%E8%A7%A3%E6%9E%90%E7%B1%BB&ie=utf-8
我感觉百度上搜索几个字,都要比在这里发帖快吧,不要老是拿来主义

#10


引用 9 楼 GLSC_CENA 的回复:
http://www.baidu.com/s?wd=vc+xml+%E8%A7%A3%E6%9E%90%E7%B1%BB&ie=utf-8
我感觉百度上搜索几个字,都要比在这里发帖快吧,不要老是拿来主义

什么拿来主义,我的这个问题是我自己解决的,拿了谁的?你的么?

#11


引用 9 楼 GLSC_CENA 的回复:
http://www.baidu.com/s?wd=vc+xml+%E8%A7%A3%E6%9E%90%E7%B1%BB&ie=utf-8
我感觉百度上搜索几个字,都要比在这里发帖快吧,不要老是拿来主义


为此贴整理出了一篇博文,留给同仁遇到相同或类似的问题时提供参考。
http://blog.csdn.net/qq2399431200/article/details/17583171


内容重点摘要:
a.创建xml文档对象  
    MSXML2::IXMLDOMDocumentPtr pDoc; //声明xml文档指针  
    HRESULT hr = pDoc.CreateInstance(__uuidof(MSXML2::DOMDocument30));  //实例化xml文档对象  
    delete pDoc;    
b.创建"Element"、添加"Element"到xml文档对象中  
    MSXML2::IXMLDOMElementPtr xmlRoot;  //声明"Element"指针  
    pDoc->raw_createElement( (_bstr_t)(char*)"China", &xmlRoot);  //创建"Element"  
    pDoc->raw_appendChild(xmlRoot, NULL);  //添加"Element"到xml文档对象中  
  
c.为"Element"添加属性及其属性值  
    MSXML2::IXMLDOMElementPtr pElemNode;  
    pDoc->raw_createElement( (_bstr_t)(char*)"City", &childNode);  
    pElemNode->setAttribute("population","7000");  //1:属性名  2:属性值  
  
d.元素之间的Text操作  
    MSXML2::IXMLDOMElementPtr pElemNode;  //声明一个元素(Element)指针  
    pElemNode->Puttext("shanghai");  //设置Element之间的Text  
    CString strElemText = (char*)(_bstr_t)pElemNode->Gettext();  //获取Element之间的Text  
          
 e.创建、保存XML文档  
    pDoc->save(".\\test.xml");  //创建、保存并关闭xml文档  
  
f.加载xml文档  
    MSXML2::IXMLDOMDocumentPtr pDoc;  
    HRESULT loadrs = pDoc->load(".\\test.xml");  //加载xml文档  
  
g.查询"Element"  
    //查询到一个或多个节点,返回第一个节点;如果没有查询的任何节点返回 Nothing  
    pElemNode = (MSXML2::IXMLDOMElementPtr)(pDoc->selectSingleNode("//City"));  //获取元素的信息  
  
h.与xml一起常用的容器  
    //IXMLDOMNamedNodeMap 是一个结点容器,允许通过name或index访问     
    //这个容器是通常用于容纳属性      
    MSXML2::IXMLDOMNamedNodeMapPtr pAttrs = NULL;  
  
    //IXMLDOMNodeList 是一个动态容器,也就是说:添加、删除结点    
    //以及改变结点,都会立即更新容器       
    MSXML2::IXMLDOMNodeListPtr nodeList = NULL;  
  
    //结点指针  
    MSXML2::IXMLDOMNodePtr pAttrItem = NULL;  
  
j.容器的使用  
    pElemNode->get_attributes(&pAttrs); //获取pElemNode指向的元素的属性集  
    pElemNode->get_childNodes(&nodeList);  //获取子节点  
  
    long nCount, iCount;  
    //IXMLDOMNamedNodeMapPtr->get_length(long* )  返回容器中保存属性的个数  
    pAttrs->get_length(&nCount);     //获取结点属性个数 2  
      
    //IXMLDOMNodeListPtr->get_length(long* ) 返回容器中保存结点的个数  
    nodeList->get_length(&iCount);   //获取子结点个数  1  
    for(int i = 0; i < iCount; i++ ) //根据需要可以添加数据到ListControl中  
    {  
        CString strElemText = (char*)(_bstr_t)pElemNode->Gettext();  //获取Element标签之间的Text文本,Puttext(LPCSTR)为设置Text文本  
        m_list.InsertItem(i,strElemText);  //1:行索引  2:待添加的字串  
        for(int j = 0; j < nCount; j++ )  
        {  
            pAttrs->get_item(j,&pAttrItem);  //获取结点信息-结点  
            //CString strAttrName = (char*)(_bstr_t)pAttrItem->nodeName;  //当前元素(Element)指定属性的名称  
            CString strAttrVale = (char*)(_bstr_t)pAttrItem->nodeTypedValue;  //当前元素指定属性的值  
              
            m_list.SetItemText(i,j+1,strAttrVale);  //1:行索引  2:列索引  3:待添加的字串  
            //m_list.SetItemText(i,2,strAttrName);   
        }  
    }  
  
k.重要的函数  
  <1>获取子元素  
     IXMLDOMNodeListPtr nodelist=NULL;  
     pElemNode->get_childNodes(&nodeList);   //两个函数是等效的  
     nodelist = pElemNode->GetchildNodes();  
     保存pElementNode元素下的所有指向子元素的指针。  
        <book category="children">  
            <title lang="en">Harry Potter</title>  
            <author>J K. Rowling</author>  
            <year>2005</year>  
            <price>29.99</price>  
        </book>  
     如pElement指向 <book> </book>,则<title>、<author>、<year>、<price>都是pElement的子结点(或称为子元素)  
    
  <2>返回nodeList容器中当前结点(应该是一个游标指针来实现的)的下一个结点。  
     nodeList->nextNode()  
     例子:  
     pElemNode = pDoc->selectSingleNode("//China");  //获取元素的信息  
     MSXML2::IXMLDOMNodeListPtr nodeList = NULL;  //list容器  
     pElemNode->get_childNodes(&nodeList);   //获取子节点  
     pCurNode = nodeList->nextNode();  
  
  <3>pCurNode->GetnextSibling()  
     Retrieves the next sibling(元素处于同一树层级中) of this node in the parent's child list.如果无此节点,则返回 null。  
     备注:目前用法没有验证。  
     可配合下面两个函数使用:  
     get_firstChild  Retrieves the first child of this node.  
     get_lastChild   Retrieves the last child of this node.  
     
  <4>获取元素的属性值  
     <City population="12000" name="Wuhan"> </City>  
     m_pCurNode指向<City> </City>这个元素  
     CString varVal = m_pCurNode->getAttribute("population");  //varVal = "12000" 


#12


xml解析, 网上有很多开源的代码,很好用, 不用这么麻烦的,

比如。 tinyxml 等。。

#13


针对这个问题我总结出一些VC下读取xml文件的用法,内容在 http://blog.csdn.net/qq2399431200/article/details/17583171博文中,看到这篇帖子的朋友可以看看!

#14


博文中有两个完整的工程实例,可以下载下来看看!谢谢以上朋友的帮助,结贴。

#15


楼主威武 VC++ 读取xml文件包含中文就出错,如何才能支持中文(宽字符)

#1


中文的问题?lz试下这个,在接口初始化之前调用:setlocale(LC_ALL,"chs");
完成之后再调用setlocale设置回原来的模式

#2


引用 1 楼 sd__q 的回复:
中文的问题?lz试下这个,在接口初始化之前调用:setlocale(LC_ALL,"chs");
完成之后再调用setlocale设置回原来的模式



setlocale(LC_ALL,"chs");  //设置语言环境 包含<locale.h>
::CoInitialize(NULL);  //初始化COM
MSXML2::IXMLDOMDocumentPtr pDoc;  //创建一个xml文档指针
HRESULT hr = pDoc.CreateInstance(__uuidof(MSXML2::DOMDocument30));  //实例化文档指针
if(!SUCCEEDED(hr))
{
MessageBox("初始化错误");
return FALSE;
}

//加载  竟然不支持“宽字符”
VARIANT_BOOL loadrs = pDoc->load(".\\DirectBtnsInfo.xml");  //加载xml文档
    if( -1 != loadrs )  // -1表示加载成功
return FALSE;

//省略xml文档读取操作代码

setlocale(LC_ALL,"english");
::CoUninitialize();  //卸载COM


设置本地语言环境后,在调用load函数后返回来的值依然是加载失败!

#3


引用 1 楼 sd__q 的回复:
中文的问题?lz试下这个,在接口初始化之前调用:setlocale(LC_ALL,"chs");
完成之后再调用setlocale设置回原来的模式


谢谢阁下的解答,问题已经解决。问题出在xml文件中--缺少xml文件头标签:
<?xml version="1.0" encoding="gb2312"?>

并且COM接口初始化前也不需要调用setlocale函数设置本地语言(可能我的操作系统是中文版的缘故)。

#4


引用 3 楼 qq2399431200 的回复:
Quote: 引用 1 楼 sd__q 的回复:

中文的问题?lz试下这个,在接口初始化之前调用:setlocale(LC_ALL,"chs");
完成之后再调用setlocale设置回原来的模式


谢谢阁下的解答,问题已经解决。问题出在xml文件中--缺少xml文件头标签:
<?xml version="1.0" encoding="gb2312"?>

并且COM接口初始化前也不需要调用setlocale函数设置本地语言(可能我的操作系统是中文版的缘故)。

奥,之前整过一个基于gsoap webservice相关的,也需要解析xml,宽字节中文乱码设置这个就可以了

#5


xml有专用的解析类,用起来方便

#6


CMarkUp用起来更方便

#7


引用 6 楼 sunnyloves 的回复:
CMarkUp用起来更方便

好用是不用怀疑的,但是解决问题就不要逃避这个问题,虽然用它能达到这个效果。

#8


引用 5 楼 GLSC_CENA 的回复:
xml有专用的解析类,用起来方便

吊胃口么?帮忙就要力所能及,如果只有只言片语又不能实实在在帮到别人,还不如帮顶来得实在。

#9


引用 8 楼 qq2399431200 的回复:
Quote: 引用 5 楼 GLSC_CENA 的回复:

xml有专用的解析类,用起来方便

吊胃口么?帮忙就要力所能及,如果只有只言片语又不能实实在在帮到别人,还不如帮顶来得实在。


http://www.baidu.com/s?wd=vc+xml+%E8%A7%A3%E6%9E%90%E7%B1%BB&ie=utf-8
我感觉百度上搜索几个字,都要比在这里发帖快吧,不要老是拿来主义

#10


引用 9 楼 GLSC_CENA 的回复:
http://www.baidu.com/s?wd=vc+xml+%E8%A7%A3%E6%9E%90%E7%B1%BB&ie=utf-8
我感觉百度上搜索几个字,都要比在这里发帖快吧,不要老是拿来主义

什么拿来主义,我的这个问题是我自己解决的,拿了谁的?你的么?

#11


引用 9 楼 GLSC_CENA 的回复:
http://www.baidu.com/s?wd=vc+xml+%E8%A7%A3%E6%9E%90%E7%B1%BB&ie=utf-8
我感觉百度上搜索几个字,都要比在这里发帖快吧,不要老是拿来主义


为此贴整理出了一篇博文,留给同仁遇到相同或类似的问题时提供参考。
http://blog.csdn.net/qq2399431200/article/details/17583171


内容重点摘要:
a.创建xml文档对象  
    MSXML2::IXMLDOMDocumentPtr pDoc; //声明xml文档指针  
    HRESULT hr = pDoc.CreateInstance(__uuidof(MSXML2::DOMDocument30));  //实例化xml文档对象  
    delete pDoc;    
b.创建"Element"、添加"Element"到xml文档对象中  
    MSXML2::IXMLDOMElementPtr xmlRoot;  //声明"Element"指针  
    pDoc->raw_createElement( (_bstr_t)(char*)"China", &xmlRoot);  //创建"Element"  
    pDoc->raw_appendChild(xmlRoot, NULL);  //添加"Element"到xml文档对象中  
  
c.为"Element"添加属性及其属性值  
    MSXML2::IXMLDOMElementPtr pElemNode;  
    pDoc->raw_createElement( (_bstr_t)(char*)"City", &childNode);  
    pElemNode->setAttribute("population","7000");  //1:属性名  2:属性值  
  
d.元素之间的Text操作  
    MSXML2::IXMLDOMElementPtr pElemNode;  //声明一个元素(Element)指针  
    pElemNode->Puttext("shanghai");  //设置Element之间的Text  
    CString strElemText = (char*)(_bstr_t)pElemNode->Gettext();  //获取Element之间的Text  
          
 e.创建、保存XML文档  
    pDoc->save(".\\test.xml");  //创建、保存并关闭xml文档  
  
f.加载xml文档  
    MSXML2::IXMLDOMDocumentPtr pDoc;  
    HRESULT loadrs = pDoc->load(".\\test.xml");  //加载xml文档  
  
g.查询"Element"  
    //查询到一个或多个节点,返回第一个节点;如果没有查询的任何节点返回 Nothing  
    pElemNode = (MSXML2::IXMLDOMElementPtr)(pDoc->selectSingleNode("//City"));  //获取元素的信息  
  
h.与xml一起常用的容器  
    //IXMLDOMNamedNodeMap 是一个结点容器,允许通过name或index访问     
    //这个容器是通常用于容纳属性      
    MSXML2::IXMLDOMNamedNodeMapPtr pAttrs = NULL;  
  
    //IXMLDOMNodeList 是一个动态容器,也就是说:添加、删除结点    
    //以及改变结点,都会立即更新容器       
    MSXML2::IXMLDOMNodeListPtr nodeList = NULL;  
  
    //结点指针  
    MSXML2::IXMLDOMNodePtr pAttrItem = NULL;  
  
j.容器的使用  
    pElemNode->get_attributes(&pAttrs); //获取pElemNode指向的元素的属性集  
    pElemNode->get_childNodes(&nodeList);  //获取子节点  
  
    long nCount, iCount;  
    //IXMLDOMNamedNodeMapPtr->get_length(long* )  返回容器中保存属性的个数  
    pAttrs->get_length(&nCount);     //获取结点属性个数 2  
      
    //IXMLDOMNodeListPtr->get_length(long* ) 返回容器中保存结点的个数  
    nodeList->get_length(&iCount);   //获取子结点个数  1  
    for(int i = 0; i < iCount; i++ ) //根据需要可以添加数据到ListControl中  
    {  
        CString strElemText = (char*)(_bstr_t)pElemNode->Gettext();  //获取Element标签之间的Text文本,Puttext(LPCSTR)为设置Text文本  
        m_list.InsertItem(i,strElemText);  //1:行索引  2:待添加的字串  
        for(int j = 0; j < nCount; j++ )  
        {  
            pAttrs->get_item(j,&pAttrItem);  //获取结点信息-结点  
            //CString strAttrName = (char*)(_bstr_t)pAttrItem->nodeName;  //当前元素(Element)指定属性的名称  
            CString strAttrVale = (char*)(_bstr_t)pAttrItem->nodeTypedValue;  //当前元素指定属性的值  
              
            m_list.SetItemText(i,j+1,strAttrVale);  //1:行索引  2:列索引  3:待添加的字串  
            //m_list.SetItemText(i,2,strAttrName);   
        }  
    }  
  
k.重要的函数  
  <1>获取子元素  
     IXMLDOMNodeListPtr nodelist=NULL;  
     pElemNode->get_childNodes(&nodeList);   //两个函数是等效的  
     nodelist = pElemNode->GetchildNodes();  
     保存pElementNode元素下的所有指向子元素的指针。  
        <book category="children">  
            <title lang="en">Harry Potter</title>  
            <author>J K. Rowling</author>  
            <year>2005</year>  
            <price>29.99</price>  
        </book>  
     如pElement指向 <book> </book>,则<title>、<author>、<year>、<price>都是pElement的子结点(或称为子元素)  
    
  <2>返回nodeList容器中当前结点(应该是一个游标指针来实现的)的下一个结点。  
     nodeList->nextNode()  
     例子:  
     pElemNode = pDoc->selectSingleNode("//China");  //获取元素的信息  
     MSXML2::IXMLDOMNodeListPtr nodeList = NULL;  //list容器  
     pElemNode->get_childNodes(&nodeList);   //获取子节点  
     pCurNode = nodeList->nextNode();  
  
  <3>pCurNode->GetnextSibling()  
     Retrieves the next sibling(元素处于同一树层级中) of this node in the parent's child list.如果无此节点,则返回 null。  
     备注:目前用法没有验证。  
     可配合下面两个函数使用:  
     get_firstChild  Retrieves the first child of this node.  
     get_lastChild   Retrieves the last child of this node.  
     
  <4>获取元素的属性值  
     <City population="12000" name="Wuhan"> </City>  
     m_pCurNode指向<City> </City>这个元素  
     CString varVal = m_pCurNode->getAttribute("population");  //varVal = "12000" 


#12


xml解析, 网上有很多开源的代码,很好用, 不用这么麻烦的,

比如。 tinyxml 等。。

#13


针对这个问题我总结出一些VC下读取xml文件的用法,内容在 http://blog.csdn.net/qq2399431200/article/details/17583171博文中,看到这篇帖子的朋友可以看看!

#14


博文中有两个完整的工程实例,可以下载下来看看!谢谢以上朋友的帮助,结贴。

#15


楼主威武 VC++ 读取xml文件包含中文就出错,如何才能支持中文(宽字符)