C++如何解析XML

测试程序在设计通用library的时候,一般会采用xml作为configuration file。利用xml的树形结构的优势,可以提供复杂的输入参数,test library读入xml的这些leaf数据后,生成测试的sequence实现测试需求。其优势如下:

  • xml本身的树形结构适合定义任意个数,任意层级嵌套的复杂参数输入(csv一般只能定义某一层和固定数目的参数);
  • xml本身有XSD schema可以很好的定义树形结构,以及各个枝叶的数据类型,出现次数等约束。输入的xml可以先和预定义的xsd进行形式化验证,保证输入的有效性,避免test library太多的xml本身合法性的检查

w3school.com.cn/schema/

  • test library设计的通用性,可扩展性以及移植性好,可以方便的使用在不同产品中

C++有很多库可以解析xml文件,一般tinyxml比较常用。但是采用该实现方式的缺点如下:

  • tinyxml是直接读取xml的,一般要求leaf数据是string类型,需要在code根据不同字段转换为合适的数据类型(比如double,int...etc)
  • 一般xsd定义的树形结构很复杂,但是每个xml可能只包含树形的一部分(其他是optional),那么根据少数xml写的code很大可能无法处理所有的该类型xml,验证的工作很重;

更合理的实现方式如下:

  • 根据测试需求定义xsd文件,保证树形定义的完备性

xsd文件一般分为以下几个部分:

- leaf的数据类型定义,这些数据类型会被下面的leaf reference

- element的树状结构定义,下图可以清楚的看到从root开始,一级一级如何伸展的,以及每一个枝叶的出现次数和数据类型;

  • 使用code synthesis提供的xsd工具,将xsd转为C++的*.hpp和 *.cpp

具体命令如下,将xsd转为cxx-tree的*.hpp和 *.cpp。注意因为使用了option --root-element-first, xsd的第一个element必须是root,否则转出来的文件有问题

xsd cxx-tree --hxx-suffix .hpp --cxx-suffix .cpp -output-dir <output_dir> --show-sloc --generate-doxygan --root-element-first --function-naming lcc --type-name ucc --proprietary-license --generate-polymorphic --polymorphic-type-all <xsd file>


  • 将转出的*.hpp和 *.cpp拷到test library,该c++ code已经将xsd树形结构转化为class;

xsd生成的*.hpp作为include,定义method读取xml文件,已经定义private methods去解析树形结构的每一类枝叶。

读取xml的code非常简单, 用root读取xml文件,然后用iteration去逐级访问每个枝叶

如果某个枝是optional的,那么需要先用present()检查是否存在,然后再访问该枝get()


总之采用该实现方式可以保证xml解析的完备性,而且不需要考虑数据类型转换,因为每个leaf的数据类型已经被class定义好了,只需要直接使用就好了。

希望本文可以帮助有xml解析需求的工程师,正确的使用xsd可以保证code的质量。

发布于 2019-11-26 23:16