新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> DTD, XML Schema(XMLS), RELAX NG
    [返回] 中文XML论坛 - 专业的XML技术讨论区XML.ORG.CN讨论区 - XML技术『 DTD/XML Schema 』 → 技巧:如何利用Xerces-C++解析包含中文字符的XML文档 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 8106 个阅读者浏览上一篇主题  刷新本主题   平板显示贴子 浏览下一篇主题
     * 贴子主题: 技巧:如何利用Xerces-C++解析包含中文字符的XML文档 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     anchen0617 帅哥哟,离线,有人找我吗?双子座1983-6-17
      
      
      威望:5
      等级:大二(研究C++)
      文章:281
      积分:3413
      门派:XML.ORG.CN
      注册:2004/10/17

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给anchen0617发送一个短消息 把anchen0617加入好友 查看anchen0617的个人资料 搜索anchen0617在『 DTD/XML Schema 』的所有贴子 访问anchen0617的主页 引用回复这个贴子 回复这个贴子 查看anchen0617的博客楼主
    发贴心情 技巧:如何利用Xerces-C++解析包含中文字符的XML文档

    Xerces-C++是目前广泛使用的XML解析器,在利用它编写XML应用以处理包含中文字符的XML文档时会出现字符编码错误,如何正确解决这个问题,对于我们开发XML的应用程序非常有用。本文给出了正确处理的方法和实现类的代码,希望能对大家有所帮助。
    1.背景介绍
    随着XML技术的普及应用,我国的各行各业有可能会生成大量的包含中文字符的XML文档。尽管基于Java技术的XML Parser能较好处理这些XML文档,但是,它不能解决所有的问题,原因是应用开发的复杂性,尤其在我国更为明显.我们知道,企业的许多应用系统的开发采用了C、C++、VB、Delphi、FoxPro等等语言,这些应用不可能用Java语言重新实现,那么,问题就出现了,如何让这些应用也能处理XML文档,甚至是包含中文字符的XML文档呢?

    目前有关XML Parser C++语言的实现,非常著名的有Apache组织的Xerces和IBM的XML4C。Aparche的Xerces来源于IBM的XML4C,所以,它们的编程接口是一致的。二者关键的不同在于字符编码。Apache的Xerces1.6目前只支持少数的字符编码,如ASCII, UTF-8, UTF-16, UCS4, EBCDIC IBM037 和 IBM1140, ISO-8859-1 和Windows-1252。因而,采用Apache的Xerces C++解析器不能处理包含中文字符的XML文档。IBM的XML4C支持多达100种字符编码,它将Xerces和International Components for Unicode (ICU)结合了起来。因而,我们可以选用XML4C作为XML的解析器。在使用XML4C之前,我们需要首先确认XML4C的bin目录是否包含在系统的Path之中,bin目录必须要有这些dll:xerces-c_1_6_0D.dll,icudt20.dll,icuuc20.dll,icuuc20d.dll。

    2. 问题描述
    在XML4C应用过程中,我发现调用XML4C提供的一些API并不能很好解决中文问题。如解析XML时生成DOM_Document, 并利用DOM方法得到某一DOM_Node节点时,为了获得DOM_Node的名字或值,需要调用DOM_Node类的getNodeName()或getNodeValue()方法,并得到DOMString对象。根据API文档描述,DOMString类的transcode()方法,返回字符串的拷贝,并依照本地代码页对此字符串进行编码处理。因而,我在解析图1的XML文档并试图获得"爱国的人们"节点的名字时,transcode方法返回不完整的节点名"爱国",而不是完整的"爱国的人们",这样,我们就无法利用这些信息来进行字符串比较等等操作,XML的处理就会出现问题。因而,DOMString的transcode方法并不能处理XML的中文字符。


    <?xml version='1.0' encoding='GB2312' ?>
    … …
            <爱国的人们>
      … …
    </爱国的人们>
        …  …

    图 1

    3.解决的方法
    针对这种情况,我仔细分析了XML4C提供的DOMPrint例子,此例子能顺利解析含中文字符的XML文档,并能打印出XML解析后生成的DOM_Document。它利用了Xerces的XMLFormatter和XMLFormatTarget类:

    XMLFormatter类,提供基本的格式化字符串功能,将解析器生成的基于Unicode的XML数据转换为非Unicode环境中使用的数据,如本地字符编码等;
    XMLFormatTarget类,为XMLFormatter格式化字符串提供目的地,它需要派生,并利用它的writeChars()方法得到格式化后的字符串。

    基于以上分析,我改进了DOMPrint的例子程序,实现了一个XMLFormatTarget类的子类,代码如下:
    //类定义
    #include <framework/XMLFormatter.hpp>
    class StrFormatTarget : public XMLFormatTarget
    {
    public:
     char * GetResult();
        StrFormatTarget()  {};
        ~StrFormatTarget () {};

        void writeChars(const   XMLByte* const  toWrite,
                        const   unsigned int    count,
                         XMLFormatter * const formatter);
      private:
     char * buffer;
        StrFormatTarget (const StrFormatTarget & other);
        void operator=(const StrFormatTarget & rhs);
    };
     //类的实现
    void StrFormatTarget::writeChars(const   XMLByte* const  toWrite,
                        const   unsigned int    count,
                        XMLFormatter * const formatter)
        {
     buffer = (char *)malloc(count + 1);
     memset(buffer,0,count+1);
     memcpy(buffer, (char *) toWrite, count);
     };
    char * StrFormatTarget::GetResult()
    {
     char * ret = (char *)malloc(strlen(buffer) +1);
     strcpy(ret, buffer);
     ret[strlen(buffer)] = 0;
     free(buffer);
     return ret;
    }


    XML文档的编码定义由文档头<?xml version='1.0' encoding='…' ?>给出,支持中文字符编码,我们选用'GB2312'。Encoding信息的获取可以有两种方式,第一,可以直接分析xml字符串,得到encoding的值;第二,利用DOMParser解析XML文档时,设定parser能创建XMLDeclType节点,即:  DOMParser parser;
     …
    parser.setToCreateXMLDeclTypeNode(true).


    在利用XML4C编程时,我们常遇见的类型是DOMString,XMLCh *,我们需要将这些类型的数据都转换为char *,然后,进行字符串的各种处理。我这里给出了一个类StrTransformer,专门解决有关字符编码的问题,它不仅仅支持中文字符编码,而且,可支持XML4C的其它字符编码。核心代码如下:
    // header file
    class StrTransformer  
    {
    public:
     char * ChangeStr(const DOMString& s);
    char * ChangeStr(const XMLCh * str);
     StrTransformer (char * encoding);
     XMLFormatter * format;
     StrFormatTarget * target;
     ~StrTransformer();
     DOMString * m_dom;
    };

    // implement file
    #include "StrTransformer.h"
    #include <stdlib.h>
    #include <util/XMLString.hpp>

    // Construction/Destruction
    StrTransformer::StrTransformer(char * encoding)
    {
     target = new StrFormatTarget();
     m_dom = new DOMString(encoding);
     format = new XMLFormatter(m_dom->rawBuffer(), target,
    XMLFormatter::NoEscapes, XMLFormatter::UnRep_CharRef);
    }

    StrTransformer::~StrTransformer()
    {
     delete target;
     delete m_dom;
     delete format;
    }

    char * StrTransformer::ChangeStr(const DOMString &s)
    {
     unsigned int lent = s.length();

     if (lent <= 0)
      return NULL;
        XMLCh*  buf = new XMLCh[lent + 1];
        XMLString::copyNString(buf, s.rawBuffer(), lent);
        buf[lent] = 0;
        *format<< buf;
        delete [] buf;
     return target->GetResult();
    }
    char * StrTransformer::ChangeStr(const XMLCh * str) {
     DOMString dom(str);
     return ChangeStr(dom);


    4 结束语
    正确处理含有中文字符的XML文档,对于我们开发XML的应用程序非常有用,希望我的方法能为你提供帮助,如果有其它建议或疑问,欢迎与我联系(f_jian@sina.com)。


       收藏   分享  
    顶(0)
      




    ----------------------------------------------
    xml这门语言太好了,我们共同努力吧!!!!!

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2004/11/13 14:31:00
     
     GoogleAdSense双子座1983-6-17
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 DTD/XML Schema 』的所有贴子 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2024/4/19 10:20:48

    本主题贴数1,分页: [1]

     *树形目录 (最近20个回帖) 顶端 
    主题:  技巧:如何利用Xerces-C++解析包含中文字符的XML文档(5488字) - anchen0617,2004年11月13日

    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    3,140.625ms