C++解析XML

TinyXml是一个基于DOM模型的、非验证的轻量级C++解释器。
1.      SAX和DOM
目前XML的解析主要有两大模型:SAX和DOM。
其中SAX是基于事件的,其基本工作流程是分析XML文档,当发现了一个新的元素时,产生一个对应事件,并调用相应的用户处理函数。这种方式占用内存少,速度快,但用户程序相应得会比较复杂。
而DOM(文档对象模型),则是在分析时,一次性的将整个XML文档进行分析,并在内存中形成对应的树结构,同时,向用户提供一系列的接口来访问和编辑该树结构。这种方式占用内存大,速度往往慢于SAX,但可以给用户提供一个面向对象的访问接口,对用户更为友好。

2.      验证和非验证

对于一个特定的XML文档而言,其正确性分为两个层次。首先是其格式应该符合XML的基本格式要求,比如第一行要有声明,标签的嵌套层次必须前后一致等等,符合这些要求的文件,就是一个合格的XML文件,称作well-formatted。但除此之外,一个XML文档因其内容的不同还必须在语义上符合相应的标准,这些标准由相应的DTD文件或者Schema文件来定义,符合了这些定义要求的XML文件,称作valid。

因此,解析器也分为两种,一种是验证的,即会跟据XML文件中的声明,用相应的DTD文件对XML文件进行校验,检查它是否满足DTD文件的要求。另一种是忽略DTD文件,只要基本格式正确,就可以进行解析。

 验证的解析器通常都是比较重量级的。TinyXml不支持验证,但是体积很小,用在解析格式较为简单的XML文件,比如配置文件时,特别的合适。
 

查询速度的问题不在于XML,而在于存储XML的方式。如果是普通的文件方式,xml不适合很大数量数据的处理。比如,如果xml文件超过10M,你就必须采用SAX来处理,XMLDOM就没有办法了,但如果你存储在XML数据库里,则就要看该数据库对XML查询的支持和优化程度。

xml文件如果比较深,遍利的时间就长,可以从算法上考虑,也可以从xml文件设计上考虑。  当然更推荐用SAX,他只把需要的内容加载到内存,这样检索的速度快了,DOM需要把整个xml文件加载到内存。

Visual Graph是一个矢量图控件,整个 Visual Graph 文件是 XML 文档格式,程序员可以把文件存放在数据库中,进行读写。 每个图形也有自己的XML格式,可以单独存取。 图形和图库是统一的XML格式,便于传输、存储和维护,支持WEB开发.采用图形文档和图库文档统一的 XML 格式,你可以任意自由地画图,任意设计属性、函数、事件,这样相当于给图形赋予了生命,设计好的图形文件马上就可以被当作图库来使用,这样通过多层嵌套,就可以设计非常复杂的图形出来,这样紧凑的结构、巧妙的设计,这是一种二维矢量绘图工具,这是一种面向对象的脚本编程语言。应用于电力行业,图形拓扑,矢量绘图,工控仿真等。http://www.visual-graph.com

 

XML     
    
  Xerces     
    
  参考网站:http://xml.apache.org/xerces-c/     
    
  Xerces-C++   是一个非常健壮的XML解析器,它提供了验证,以及SAX和DOM   API。XML验证在文档类型定义(Document   Type   Definition,DTD)方面有很好的支持,并且在2001年12月增加了支持W3C   XML   Schema   的基本完整的开放标准。     
    
  XMLBooster     
    
  参考网站:http://www.xmlbooster.com/'>http://www.xmlbooster.com/     
    
  这个库通过产生特制的parser的办法极大的提高了XML解析的速度,并且能够产生相应的GUI程序来修改这个parser。在DOM和SAX两大主流XML解析办法之外提供了另外一个可行的解决方案。     
    
  Pull   Parser     
    
  参考网站:http://www.extreme.indiana.edu/xgws/xsoap/xpp/'>http://www.extreme.indiana.edu/xgws/xsoap/xpp/     
    
  这个库采用pull方法的parser。在每个SAX的parser底层都有一个pull的parser,这个xpp把这层暴露出来直接给大家使用。在要充分考虑速度的时候值得尝试。     
    
  Xalan     
    
  参考网站:http://xml.apache.org/xalan-c/     
    
  Xalan是一个用于把XML文档转换为HTML,纯文本或者其他XML类型文档的XSLT处理器。     
    
  CMarkup     
    
  参考网站:http://www.firstobject.com/xml.htm'>http://www.firstobject.com/xml.htm     
    
  这是一种使用EDOM的XML解析器。在很多思路上面非常灵活实用。值得大家在DOM和SAX之外寻求一点灵感。     
    
  libxml++     
    
  http://libxmlplusplus.sourceforge.net/     
    
  libxml++是对著名的libxml   XML解析器的C++封装版本   Xerces   c++   --Apache的XML项目,   但   只支持少数的字符编码,如ASCII,UTF-8,UTF-16等,   
  不能处理包含中文字符的XML文档   
  但中文问题也是可以解决的。   
    
  1.   背景介绍   
    
  apache的xerces   c++是广大c/c++程序员非常喜欢使用的xml解析器之一。主要原因是其本身是一个开放源代码的项目而且提供不同平台下的库和源代码,故深受广大c/c++程序员的欢迎。   
    
  xerces   c++可以到以下网站下载:   
  1)   http://xml.apache.org/     
  2)   http://www.vckbase.com/tools   
    
    
    
    2.   问题描述   
    
  根据软件开发的要求,作者开发了一个文件特征识别软件,该软件可根据文件特有的特征识别出文件的类型。要求将文件特征保存在xml文件中。根据要求作者选择了xerces   c++作为xml解析器。但发现出了一个严重的问题:被解析的xml文件中不能包含中文,否则中文将不能正确的解析。作者研究了xerces   c++提供的例子程序,发现这些例子程序解析的结果也是错误的。只有domprint程序例外。这肯定了xerces   c++本身是支持中文的。   
  xml编码:     
    
  <pdf   ext="pdf"   description="pdf文档">     <magic   offset="0"   type="string"   value="\x25\x50\x44\x46"   />   </pdf>saxprint程序解析结果:   
  <pdf   ext="pdf"   description="pdf文档">     <magic   offset="0"   type="string"   value="\x25\x50\x44\x46"></magic></pdf>为此,作者曾经在ibm的中文网站发现一篇文章《如何利用xerces-c++解析包含中文字符的xml文档》并将其所描述的办法应用到程序中。但后来由于机器发生故障,硬盘上的数据全部丢失。不得不把以前做过的事重做一遍。因一时在ibm的网站上未找到上面提到的贴子,而且由于当时捡现成的没有用心研究其实现方法,故不得不仔细分析xerces   c++提供的源代码,自己动手解决中文问题。为了今后广大c++程序员碰到类似问题时不会像我一样痛苦。我也决定将自己的研究结果公布出来供大家分享。如果谁有更好的解决办法不要忘记告诉我。   
    
    3.   原因分析   
    
  上面的例子里,程序将“文档”两个中文字符解析成了乱码。但domprint程序确能够正确解析。这表明xerces   c++对国际编码肯定是支持的。作者通过对domprint和saxprint两个程序的比较跟踪发现问题的根本就是xmlformatter设置的问题。由于sax是基于事件的,大多数使用者只是简单的解析xml文档,xmlformatter的使用比较麻烦。而domprint也是通过标准的输出程序输出的屏幕上的,我们不能直接使用输出结果。   
  由于xml解析器解析的字符串都是xmlch格式的,一个字符占用一个字节,而汉字字符确要占用两个字节。故若不做适当的转换,汉字的输出结果就变成乱码了。   
    
    4.   解决办法   
    
  找到原因就有解决问题的方法了,明显的需要一个把解析出来的xmlch转换成普通的字符串。这是解析,如果我们需要自己写入xml文档也有一个把普通字符串转换为xmlch的过程。我把这两个转换过程封装在了一个名为“xmlstringtranslate”的类中。使用如下:   
    
  void   saxmagichandlers::startelement(const   xmlch*   const   name,attributelist&   attributes){ xmlstringtranslate   stringtranslate("gb2312"); string   strname=stringtranslate.translate(name);//得到可包含汉字字符的普通字符串 string   strvalue="pdf文档"; xmlch   *   value=   stringtranslate.translate(strvalue.c_str());//将普通字符串转换成xmlch串}采用xmlstringtranslate后的实际运行结果:     
  <pdf   ext="pdf"   description="pdf文档">     <magic   offset="0"   type="string"   value="\x25\x50\x44\x46"></magic></pdf>特别说明:   
  由于为了防止内存释放问题,将普通字符串转换成xmlch   *的translate函数返回的是类的一个成员变量,故下面的代码是不允许的:     
  xmlch   *   value1=   stringtranslate.translate("测试1");xmlch   *   value2=   stringtranslate.translate("测试2");这样使用的结果是value1和value2的值将是一样的(因为其内存地址根本就是一样的)。正确的使用方法是通过内存拷贝或则其他方法,将value1的值保存起来或则及时使用,否则value2将影响value1的值。

除了   Xerces   ,还可以考虑   MS   的   MSXML::   
    
  VC使用MSXML解析XML文档   
    
            现在XML文档应用的方面特别的多.   
    
            我把以前写过的一个例子帖出来,以备以后使用.   
    
            第一部分:DOM解析:   
    
            概述:DOM解析将会把一个完整的XML文档读进来,生成一个结构树。这样会要把XML文档全部都加载到内在中。所以解析起来的速度会要慢一些。   
    
            1、如何加载xml文件:   
    
                    //创建DOM,加载XML文档   
                    MSXML::IXMLDOMDocumentPtr   pCommandDoc;   
                    pCommandDoc.CreateInstance(__uuidof(MSXML::DOMDocument));   
                      pCommandDoc->put_async(VARIANT_FALSE);   
                      pCommandDoc->put_validateOnParse(VARIANT_FALSE);   
                      pCommandDoc->put_resolveExternals(VARIANT_FALSE);   
                      pCommandDoc->put_preserveWhiteSpace(VARIANT_TRUE);   
                      pCommandDoc->load(file.GetBuffer(0));   
    
            2、在XML文档中查找指定的结点:   
    
              //找到   
            MSXML::IXMLDOMNodePtr   pRootNode=pCommandDoc->selectSingleNode("root/record");   
                if   (pRootNode==NULL)   
            {   
                      return   ;   
              }   
    
          3、得到XML文档中,结点的属性   
    
                  CString   strTemp;   
            MSXML::IXMLDOMNamedNodeMapPtr   pAttrs   =   NULL;   
            pRootNode->get_attributes(&pAttrs);   
            if   (pAttrs==NULL)   
            {   
                      return;   
            }   
            MSXML::IXMLDOMNodePtr   pRequestTypeAttr=pAttrs->getQualifiedItem("name","");   
            _bstr_t   strRequestType=pRequestTypeAttr->Gettext();   
            strTemp=strRequestType.operator   char   *();   
    
          4、得到结点的内容   
    
          _bstr_t   strVisiPort=pNode->Gettext();   
    
          5、设置结点的内容   
    
            HRESULT   hr=pNode->put_text(_bstr_t(m_strGatewayPassword));   
    
    
        6、设置一个属性内容   
          IXMLDOMAttribute   *pa=NULL;   
          bstr   =   SysAllocString(L"属性1");   
          pXMLDom->createAttribute(bstr,&pNode);     
          var   =   VariantString(L"strin");   
          pa->put_value(var);   
          pRoot->setAttributeNode(pa,   &pa1);   
          
            第二部分、如何使用SAX解析   
    
            概述:SAX使用的是加载式的,将会把XML文档分断,加载到内存中。使用事件通知的方式,来表示找到结点。好像没有写文档的能力吧。它的速度要比DOM快不少。   
    
            使用SAX的时候,就需要重载MSXML4.0中的一个接口ISAXContentHandler。   
    
            有几个函数重载了之后,当找到了结点之后,就会回调这一些函数。  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值