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

    >> XML编辑器,XML解析器,XML开发环境
    [返回] 中文XML论坛 - 专业的XML技术讨论区XML.ORG.CN讨论区 - XML技术『 XML工具及XML开发环境 』 → XML映射c语言结构源代码自动化工具 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 6640 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: XML映射c语言结构源代码自动化工具 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     BetonArmEE 帅哥哟,离线,有人找我吗?
      
      
      等级:大一新生
      文章:3
      积分:66
      门派:XML.ORG.CN
      注册:2007/3/20

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给BetonArmEE发送一个短消息 把BetonArmEE加入好友 查看BetonArmEE的个人资料 搜索BetonArmEE在『 XML工具及XML开发环境 』的所有贴子 引用回复这个贴子 回复这个贴子 查看BetonArmEE的博客楼主
    发贴心情 XML映射c语言结构源代码自动化工具


    XML映射c语言结构源代码自动化工具
    使用文档

    calvin.xml2c@gmail.com
    2009.7

    谨以此文献给我亲爱的莫莫,她和她哥哥对网店的投入意外给了我写本文的时间。

    版本修订
    版本号 修订人 修订日期 修订内容
    0.1.0 calvin 2009-07-13 创建

    目录索引
    版本修订 3
    目录索引 4
    1.概述 5
    1.1.XML和映射c语言结构 5
    1.2.xml2c是什么 6
    1.3.感受一下XML新开发风格 6
    2.使用教程 10
    2.1.编写xmd定义文件 10
    2.2.用xml2c处理后生成的源代码文件 11
    2.3.嵌入你的应用代码 13
    3.附录 14
    I.关于作者和本文 14
    II.xmd中已实现的数据类型描述 14

    1.概述
    1.1.XML和映射c语言结构
     XML(Extensible Markup Language)即可扩展标记语言由于其跨平台性、自描述性、多层次化等优点目前被广泛使用。
    XML处理过程代码风格比较成熟,各个函数库使用大同小异,甚至函数名也一样。主流操作无非就是读入外部XML文件或缓冲区,创建XML树,遍历处理树,导出树为外部XML文件或缓冲区。其中遍历处理树普遍采用硬编码方式,增加了应用代码复杂性风险性和编码负担。
     XML和c语言结构都具备多层次化数据表达,不妨把两者建立映射关系,XML标记和c结构成员变量做元数据映射,类似于下例:
     XML数据:
      <userinfo>
       <username>calvin.xml2c@gmail.com</username>
       <password>123456</password>
       <regdate>2009-01-01</regdate>
       <logindate>2009-07-13</logindate>
       <extinfo>
        <age>30</age>
        <income>160000.00</income>
        <marriage>FALSE</marriage>
       </ extinfo>
      </userinfo>
     对应c语言结构:
      struct userinfo
      {
       char  username[ 64 + 1 ] ;
       char  password[ 8 + 1 ] ;
       char  regdate[ 10 + 1 ] ;
       char  logindate[ 10 + 1 ] ;
       struct _extinfo
       {
        int  age ;
        double income ;
        BOOL marriage ;
       } extinfo ;
      }
     以上映射关系可以用XML定义格式(xmd)来描述:
      <userinfo>
       <username>char64</username>
       <password>char8</password>
       <regdate>date</regdate>
       <logindate>date</logindate>
       <extinfo>
        <age>int</age>
        <income>money</income>
        <marriage>BOOL</marriage>
       </extinfo >
      </userinfo >

    1.2.xml2c是什么
    xml2c是基于libxml2函数库的预处理XML定义描述文件生成c语言源代码的自动化工具。开发人员针对要处理的XML,改造成xmd,用工具xml2c处理后自动生成对应的c语言结构、XML格式-c结构格式相互转换函数以及周边源代码资源。
    xml2c是跨平台的,这意味着你所能接触的几乎所有主流操作系统上都能使用它。
    xml2c最新版本是v0.9.1(试验版)。

    1.3.感受一下XML新开发风格
     以1.2.为例,实现userinfo的文件读写处理。
     稍作修改的XML定义描述文件(XML_test.xmd):(为什么要稍作修改呢?因为xml2c目前还不十分完善)
      <userinfo>
       <username>char64</username>
       <password>char8</password>
       <regdate>date</regdate>
       <logindate>date</logindate>
       <extinfo>
        <age>int</age>
        <income>double</income>
        <marriage>char5</marriage>
       </extinfo >
      </userinfo >
     执行命令 “xml2c XML_test.xmd”,用工具xml2c处理XML_test.xmd后,你会找到一堆自动生成的c源代码文件:
      XML_test.XMLSTRUCT.h 对应c语言结构定义
      XML_test.XMLDUMP.c c语言结构导出为外部XML文件或缓冲区格式转换函数
      XML_test.XMLPARSE.c 外部XML文件或缓冲区映射为c语言结构格式转换函数
      XML_test.XMLFREE.c 对变长元数据和变size数组的free操作函数
      XML_test.XMLTRIM.c 裁剪各字符串变量右边白字符函数
     (然后开发人员卷着袖子上场了)test.c:
      #include "libxml2c.h"
      #include "XML_test.XMLSTRUCT.h"
      
      int write_xmlfile()
      {
       struct XML_userinfo userinfo ;
       
       memset( & userinfo , 0x00 , sizeof(struct XML_userinfo) );
       strcpy( userinfo.username , "calvin.xml2c@gmail.com" );
       strcpy( userinfo.password , "123456" );
       strcpy( userinfo.regdate , "2009-01-01" );
       strcpy( userinfo.logindate , "2009-07-13" );
       userinfo.extinfo.age = 30 ;
       userinfo.extinfo.income = 160000.00 ;
       strcpy( userinfo.extinfo.marriage , "FALSE" );
       
       XMLDUMPFILE_userinfo( & userinfo , "test.xml" );
       
       return 0;
      }
      
      int main()
      {
       return write_xmlfile();
      }
      
     编译链接执行,生成外部XML文件:
      <?xml version="1.0" encoding="GBK"?>
      <userinfo>
        <username>calvin.xml2c@gmail.com</username>
        <password>123456</password>
        <regdate>2009-01-01</regdate>
        <logindate>2009-07-13</logindate>
        <extinfo>
          <age>30</age>
          <income>160000.000000</income>
          <marriage>FALSE</marriage>
        </extinfo>
      </userinfo>
     okay,导出完成,再试试读入
      int read_xmlfile()
      {
       struct XML_userinfo userinfo ;
       
       memset( & userinfo , 0x00 , sizeof(struct XML_userinfo) );
       XMLPARSEFILE_userinfo( "test.xml" , & userinfo );
       
       printf( "userinfo.username[%s]\n" , userinfo.username );
       printf( "userinfo.password[%s]\n" , userinfo.password );
       printf( "userinfo.regdate[%s]\n" , userinfo.regdate );
       printf( "userinfo.logindate[%s]\n" , userinfo.logindate );
       printf( "userinfo.extinfo.age[%d]\n" , userinfo.extinfo.age );
       printf( "userinfo.extinfo.income[%lf]\n" , userinfo.extinfo.income );
       printf( "userinfo.extinfo.marriage[%s]\n" , userinfo.extinfo.marriage );
       
       return 0;
      }
     编译链接执行,显示:
      userinfo.username[calvin.xml2c@gmail.com]
      userinfo.password[123456]
      userinfo.regdate[2009-01-01]
      userinfo.logindate[2009-07-13]
      userinfo.extinfo.age[30]
      userinfo.extinfo.income[160000.000000]
      userinfo.extinfo.marriage[FALSE]
     Well done , that’s all ~
     总结一下流程:首先编写或者改造现有的XML文件为定义文件,用工具xml2c处理生成c结构定义和格式转换函数,在你的应用代码中声明结构变量,调用自动生成的函数们做结构变量和XML文件或缓冲区格式相互转化。
     对于变长字符串类型映射成c语言字符指针,重复相同层次结构的XML子树映射成c结构数组。
     您老感觉如何?如果吓着您了,就当浪费您时间不用往下看了,如果您眼光变绿口水直淌——欢迎进入第二章^_^
     
    2.使用教程
    2.1.编写xmd定义文件
     xmd文件就是一个普通的XML文件,原有层次结构保持不变,只不过数据部分用类型描述替代,比如把“<age>30</age>” 替代成“<age>int</age>”,把“<username>calvin.xml2c@gmail.com</username>”替代成“<username>char64</username>”,完整的类型描述参见附录II。
     目前版本xml2c支持变长字符串类型和重复XML相同层次结构,前者映射成c语言字符指针,由XML读函数内部在堆中alloc内存空间,后者映射成定长或变长结构数组,声明_count变量和_size变量跟踪该结构数组的大小。一个典型的案例如下:
      <?xml version="1.0" encoding="GBK"?>
      <tree>
       <branch11>char64</branch11>
       <branch12>char*</branch12>
       <branch21>
        <leaf211>short</leaf211>
        <leaf212>int</leaf212>
        <branch213>
         <leaf2131>long</leaf2131>
        </branch213>
       </branch21>
       <branch22 iterative="2">
        <leaf221>double</leaf221>
       </branch22>
       <branch23 iterative="*">
        <leaf231>datetime</leaf231>
       </branch23>
      </tree>
     这里要注意的是如果你的xmd有XML头(“<?xml version="1.0" encoding="GBK"?>”),工具xml2c会提取出编码代码影响后面生成的所有源代码。
    xmd定义文件最原始的来源渠道就是手工写,有些人喜欢用XML编辑器,比如XMLSpy(目前本人还没下载到完美破解的版本),有些人习惯干净,喜欢用记事本或者UltraEdit书写,更多的懒人则喜欢直接把XML文件拿来,把数据部分改成类型描述即可。

    2.2.用xml2c处理后生成的源代码文件
     定义好了xmd文件后,把xml2c拿出来处理一下它,如果你是一个严谨仔细的人,那么在标准输出最后一行出现的应该是“ok!\n”,如果没有出现,一定是哪里出现了错误,返回修改你的xmd直到pass为止。(推荐xmd文件命名规则为“XML_xxxxxx.xmd”,其中xxxxxx你可以自由命名)
    你所在的目录里出现了很多c语言源代码文件,假如用的是1.3.的xmd文件,应该生成如下源代码文件:
      --- XML_test.XMLSTRUCT.h ---------
      #ifndef _H_XML_test_XMLSTRUCT_
      #define _H_XML_test_XMLSTRUCT_
      
      #include "libxml2c.h"
      
      struct XML_userinfo
      {
       char username[ 64 + 1 ] ;
       char password[ 8 + 1 ] ;
       char regdate[ 10 + 1 ] ;
       char logindate[ 10 + 1 ] ;
       struct _extinfo
       {
        int age ;
        double income ;
        char marriage[ 5 + 1 ] ;
       } extinfo ;
      } ;
      
      int XMLDUMPBUFFER_userinfo( struct XML_userinfo *pst , char *pbuffer , int *pbuflen );
      int XMLDUMPFILE_userinfo( struct XML_userinfo *pst , char *xmlfilename );
      int XMLPARSEBUFFER_userinfo( char *pbuffer , int *pbuflen , struct XML_userinfo *pst );
      int XMLPARSEFILE_userinfo( char *xmlfilename , struct XML_userinfo *pst );
      
      int XMLTRIM_userinfo( struct XML_userinfo *pst );
      int XMLFREE_userinfo( struct XML_userinfo *pst );
      
      #endif
    头文件里包含对应c结构定义,以及其它几个.c文件里实现的函数原型。
    函数XMLDUMPBUFFER_userinfo和XMLDUMPFILE_userinfo用于导出c结构变量数据到你申请好的缓冲区或外部XML文件,函数实现自动生成放在XML_test.XMLDUMP.c。
      --- XML_test.XMLDUMP.c ---------
      #include "libxml2c.h"
      #include "XML_test.XMLSTRUCT.h"
      
      int XMLDUMP_userinfo( struct XML_userinfo *pst , xmlDoc *pXmlDoc , xmlNode **ppXmlNode )
      {...}
      int XMLDUMPBUFFER_userinfo( struct XML_userinfo *pst , char *pbuffer , int *pbuflen )
      {...}
      int XMLDUMPFILE_userinfo( struct XML_userinfo *pst , char *xmlfilename )
      {...}
    函数XMLPARSEBUFFER_userinfo和XMLPARSEFILE_userinfo用于读入缓冲区或外部XML文件映射成c结构数据,函数实现自动生成放在XML_test.XMLPARSE.c。
      --- XML_test.XMLPARSE.c ---------
      #include "libxml2c.h"
      #include "XML_test.XMLSTRUCT.h"
      
      int XMLPARSE_userinfo( xmlDoc *pXmlDoc , xmlNode **ppXmlNode , struct XML_userinfo *pst )
      {...}
      int XMLPARSEBUFFER_userinfo( char *pbuffer , int *pbuflen , struct XML_userinfo *pst )
      {...}
      int XMLPARSEFILE_userinfo( char *xmlfilename , struct XML_userinfo *pst )
      {...}
    函数XMLTRIM_userinfo用于裁剪元数据类型为字符串的右边白字符,函数实现自动生成放在XML_test.XMLTRIM.c。
      --- XML_test.XMLTRIM.c ---------
      #include "libxml2c.h"
      #include "XML_test.XMLSTRUCT.h"
      
      int XMLTRIM_userinfo( struct XML_userinfo *pst )
      {...}
    函数XMLFREE_userinfo用于释放变长字符串和变长结构数组在堆上申请的内存空间,函数实现自动生成放在XML_test.XMLFREE.c。
      --- XML_test.XMLFREE.c ---------
      #include "libxml2c.h"
      #include "XML_test.XMLSTRUCT.h"
      
      int XMLFREE_userinfo( struct XML_userinfo *pst )
      {...}

    2.3.嵌入你的应用代码
     有了所有素材,你的应用代码编码变得简单。
     用前面生成的头文件里的结构体定义声明结构变量,也就是XML层次数据对应的结构,并用memset把它洗干净了。

     如果从缓冲区里读进来,用前面自动生成的函数,原型为:
      int XMLPARSEBUFFER_userinfo( char *pbuffer , int *pbuflen , struct XML_userinfo *pst );
     char *pbuffer和int *pbuflen为缓冲区首地址和有效长度,struct XML_userinfo *pst为数据映射到的c结构变量。
     如果从XML文件里读进来,用前面自动生成的函数,原型为:
      int XMLPARSEFILE_userinfo( char *xmlfilename , struct XML_userinfo *pst );
     char *xmlfilename为外部XML文件名,struct XML_userinfo *pst为数据映射到的c结构变量。

     如果写到缓冲区里去,用前面自动生成的函数,原型为:
      int XMLDUMPBUFFER_userinfo( struct XML_userinfo *pst , char *pbuffer , int *pbuflen );
     struct XML_userinfo *pst为数据源c结构变量,char *pbuffer和int *pbuflen为目标存放缓冲区首地址和缓冲区size。
     如果写到XML文件里,用前面自动生成的函数,原型为:
      int XMLDUMPFILE_userinfo( struct XML_userinfo *pst , char *xmlfilename );
     struct XML_userinfo *pst为数据源c结构变量,char *xmlfilename为要保存的外部XML文件名。

    编译链接你的应用代码,看看最终效果,并爱上她。

    3.附录
    I.关于作者和本文
     作者目前供职于某城市商业银行,崇尚创意,工作之余搞点儿研究自得其乐,在银行系统架构、基于FastCGI的现代CGI平台、源代码自动化理论、跨平台函数库等都有较深的研究和实现,并著有三部散文诗集供退休后赏玩。此外还是狂热级休闲wow玩家,国际惯例:二区(月神殿)Maua,一区(铜龙军团)暗影战刃。
     你可以通过电子邮箱calvin.xml2c@gmail.com联系我,欢迎和我交流探讨共同提高^_^

    (本工具目前为试验版本,因本工具造成的一切后果由使用者自负)
    以上这句话有点儿吓人,呵呵呵^_^

    II.xmd中已实现的数据类型描述
    XML元数据类型(xmd内表达) c语言结构成员变量类型 类型描述
    short short 短整型
    int int 整型
    long long 长整型
    float float 浮点型
    double double 双浮点型
    char?? char[ ?? + 1 ] 定长字符串型
    char* char* 变长字符串型①

    date char[ 10 + 1 ] 日期
    time char[ 9  + 1 ] 时间
    datetime char[ 19 + 1 ] 日期时间
    money double 金额②

    BOOL BOOL 布尔值②

    YESNO YESNO 是非值②

    ONOFF ONOFF 开关值②

    定个数XML子树结构 struct { } XXXXXX[ ?? ] ; 结构数组①

    不定个数XML子树结构 struct { } *XXXXXX ;
    long XXXXXX_count ;
    long XXXXXX_size ; 结构数组指针①

    ①: PARSE系列函数自动调用alloc在堆上创建空间,DUMP列表函数则需要用户自己负责分配好空间并赋值_count和_size变量;应用处理完需要用户显式调用FREE系列函数释放空间。
    ②:待实现数据类型。

    ------------------------------------------------------
    下载包地址 : http://bbs3.chinaunix.net/thread-1506492-1-2.html


       收藏   分享  
    顶(0)
      




    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2009/7/15 23:44:00
     
     GoogleAdSense
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 XML工具及XML开发环境 』的所有贴子 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2024/4/28 0:14:17

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

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    77.026ms