新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   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文档中的WhiteSpace 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 6946 个阅读者浏览上一篇主题  刷新本主题   平板显示贴子 浏览下一篇主题
     * 贴子主题: 技巧:如何利用Xerces C++正确处理XML文档中的WhiteSpace 举报  打印  推荐  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文档中的WhiteSpace

    1.背景介绍

    Apache的Xerces C++ 和IBM的XML4C是广大C/C++编程人员非常喜欢使用的XML解析器,我比较偏好XML4C,最主要的原因是它能正确处理XML文档中的中文字符,具体可参见我以前在IBM developerWorkers China上发表的文章《如何利用Xerces-C++解析包含中文字符的XML文档》。

    Xerces C++提供DOMParser和SAXParser解析XML文档,主要用途可有以下三种:

    生成DOM_Document,并调用Xerces C++的API操纵内存中的XML Tree;
    与XMLFormat等其它类结合,格式化XML文档,生成包含WhiteSpace的缩进式XML,方便使用者阅读;
    去除XML文档中多余的whiteSpace,紧缩XML文档,应用于以XML为数据格式实现消息传送的应用,尽可能降低XML传输占用的网络带宽。
    第2和第3种应用的实现比较简单,可参照Xerces C++提供的DOMPrint和SAXPrint的例子,并略做改进即可解决。而对于应用非常普遍的第一种情况,常有人会因为XML文档中的whitespace而出现程序处理问题,不能正确操纵DOM_Document表示的XML tree,从而影响了Xerces C++或XML4C上的应用开发。

    2.问题描述

    下面以Xerces C++的DOMParser为例,描述当解析含whitespace的XML文档时存在的问题,图1是部分程序代码,图2是要解析的XML文档。

    图1中的代码在创建DOMParser之后,调用了DOMParser类的setIncludeIgnorableWhitespace()方法,目的是告诉解析器不要在DOM_Document中包含whitespace,因而,根据图2所示,图1代码运行结果应为:

    List size = 1
    但是,程序实际运行的结果为:

    List size = 3
    对DOM_NodeList遍历时发现,DOMParser解析test.xml时将文档中的whitespace认为了DOM_Text节点。DOMParser没有理会setIncludeIgnorableWhitespace()方法的调用,这样,DOM_Document中会存在多个代表whitespace的DOM_Text节点,这不仅占用了多余内存,而且,极大影响了程序员对DOM_Document的操作,甚至会使子节点是否等于某值的判断始终为false。因而,Xerces C++的程序员需要在DOM_Document中过滤掉所有的whitespace,如果将test.xml中多余的whitespace去掉(见图3所示)后,重新运行图1的代码,结果与预想的相同。


    XMLPlatformUtils::Initialize();
    ... ...
    DOMParser * Parser = new DOMParser;
    Parser->setIncludeIgnorableWhitespace(false);
    Parser->parse( "test.xml" );

    DOMDocument  doc = Parser->getDocument();
    DOM_Element root = doc.getDocumentElement();
    DOM_NodeList List = root.getChildNodes();
    Int len = list.getLength();
    printf("\n list size = %d", len);
        


    图 1 相关程序代码

    <?xml version="1.0" encoding="UTF-8"?>
    <personnel>
      <person id="Big.Boss" >
        <name><family>Boss</family> <given>Big</given></name>
        <email>chief@foo.com</email>
        <link subordinates="one.worker two.worker three.worker four.worker five.worker"/>
      </person>
    </personnel>

    图 2 test.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <personnel><person id="Big.Boss" >   
    <name><family>Boss</family><given>Big</given></name>
    <email>chief@foo.com</email>
    <link subordinates="one.worker two.worker three.worker four.worker five.worker"/>
    </person>
    </personnel>

    图 3 去除whitespace后的test.xml

    显然,利用额外的程序编程解决此问题是不明智的。Xerces C++应提供了相应的机制来解决它。我用google搜索了这方面的信息,发现还是有许多人遇到了此类问题,尽管IBM论坛上有人提出了解决思路,但是,还不够完整,我在研究Xerces C++的相关资料和代码解决此问题后认为,如何利用Xerces C++正确处理xml文档中的whitespace问题需要有较详细的解释和解决方法,权当是抛砖引玉吧,希望能为Xerces C++或XML4C的普及应用有所帮助。

    3.原因分析

    根据void DOMParser::setIncludeIgnorableWhitespace (const bool include ) 的文档说明,Parser是否包含whitespace的设置仅在Parser对XML文档进行有效性验证处理时有效。因而,图2中的test.xml只能是格式良好的XML文档,由于它没有相应的schema定义,所以,DOMParser无法对此文档进行有效性验证,缺省认为whitespace是DOM_Document的子节点,类型是DOM_Text。

    那么,为test.xml提供schema之后,图1的运行结果是否正确呢?答案是不正确的,DOMParser还需要调用下列的API来设置其它选项。

    方法名 方法说明
    Void SetDoSchema(const bool newState ) 设置Parser是否处理xml文档中的schema,如果为true,则Parser还要处理xml中的schema,否则,parser不处理xml文档的schema。
    Void setDoValidation ( const bool newState ) 此方法同setValidationScheme,不推荐使用。
    Void setDoNamespaces ( const bool newState ) 设置Parser是否处理xml文档中的名域,如果为true,则Parser增强名域定义的约束和规则。
    Void setValidationScheme (const ValSchemes newScheme )  设置Parser利用定义的schema对xml文档进行有效性验证解析。NewScheme的值有Val_Never,Val_Auto,Val_Always,分别表示对xml文档不进行shema有效验证、自动选择是否验证、总是进行有效验证。

    因而,通过设置DOMParser的几个选项并提供test.xml的schema就应该能解决whitespace的问题。

    4. 解决方法

    基于上面的分析,我们首先需要为test.xml提供schema定义,这是解决此问题的第一步,也是必须的,如果不提供schema定义而想完成xml文档的紧缩处理,则需要程序员额外增加实现代码;或者使用SAXParser,在实现ContentHandler::ignorableWhitespace(const XMLCh* const chars, const unsigned int length)的纯虚方法中特殊处理,不为whitespace生成DOM_Text节点。但我这里不推荐此种处理方法,XML文档的有效性验证在许多应用系统中是必须的。

    Test.xml的schema文件定义见Xerces C++包中的文件:<xerces C++安装路径>\data\personal.xsd,相应地,test.xml中需要标注shema,详细见:<xerces C++安装路径>\data\personal-schema.xml文件,这里在图5中给出shema的声明部分。

    在上述步骤完成后,修改图1的程序代码,设置Parser支持XML文档的有效性验证,具体见图6。


    <personnel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation='personal.xsd'>
    ... ...
    </personnel>

    图 5 schema的声明

    XMLPlatformUtils::Initialize();
    ... ...
    DOMParser * Parser = new DOMParser;
    Parser->setIncludeIgnorableWhitespace(false);
    parser->setDoNamespaces(true);
    parser->setDoSchema(true);   
    parser->setValidationScheme(DOMParser::Val_Auto);
     
    parser->parse( "test.xml" );

    DOMDocument  doc = Parser->getDocument();
    DOM_Element root = doc.getDocumentElement();
    DOM_NodeList List = root.getChildNodes();
    Int len = list.getLength();
    printf("\n list size = %d", len);

    图 6 最终程序代码

    需要说明以下几点:

    XML文档和shema定义中都用到了名域,如图5中的xsi,schema定义中的xsd:element等等,所以,parser一定要设置名域的支持(调用setDoNamespaces(true)),否则,parser在解析xml的过程中会抛出异常。
    setDoValidation()方法和setValidationScheme()方法在同一程序中不应同时出现。
    注意这些方法调用之间的相互关系,例如,如果设置了对xml进行有效验证(调用setValidationScheme),而没有设置Parser对schema的处理支持(没有调用SetDoSchema),这时,DOMParser会在处理过程中抛出异常。
    最好选用Val_Auto设置DOMParser的有效性验证,由Parser根据XML中是否标记schema来确定是否需要有效性验证,这种处理会使程序较为灵活。
    5. 结束语

    目前,许多企业已经或者正在采用Xerces C++开发XML的应用系统,相信在应用的过程中会遇到各种问题,欢迎有兴趣的朋友与我联系,共同交流。


       收藏   分享  
    顶(0)
      




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

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2004/11/13 14:29: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/29 17:22:16

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

     *树形目录 (最近20个回帖) 顶端 
    主题:  技巧:如何利用Xerces C++正确处理XML文档中的WhiteSpace..(6524字) - anchen0617,2004年11月13日

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