自己写的简单xml解析器

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介:

已经自我放逐好几年了.打算去上班得了.在最后的自由日子里,做点有意义的事吧...



已经在很多正式,非正式的场合用过了.干脆开源得了.BSD授权.
代码比较久远,最后一次修改也在4~5年前了.写的比较BT,只有gcc/vc/icl能编译...
不过性能和易用性还是不错的.之前我测试过的,只有几个in place的xml解析器稍微比我的快一点点.
下面是示例代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

// xml-test.cpp

#include

#include "xml.h"

 

// 自定义FILE*输出策略

class cfile_writer {

   FILE *_fp;

   cfile_writer &operator = ( const cfile_writer& );

   cfile_writer( const cfile_writer& );

public:

   cfile_writer( FILE *fp ) : _fp(fp) {

       fputs( "-----------------\n", _fp );

   }

   ~cfile_writer() {

       fputs( "\n", _fp );

   }

   // 策略不用预分配空间

   // 如果为1, 在输出前会计算要占空间大小, 并调用resize接口进行预分配.

   static const int need_pre_allocate = 0;

   // 预分配接口

   bool resize( size_t size ) const { return true; }

   // 输出一个字符

   void write( char value ) const  {

       fputc( value, _fp );

   }

   // 输出一个字符串, 长度由size指定

   void write( const char *value, size_t size ) const  {

       fwrite( value, 1, size, _fp );

   }

};

 

int main() {

   using namespace cpp::utils;

   const char xml_string[] = "text content";

   xml x;

 

   // 解析xml_string, 用不同的reader策略可以从不同的源中读数据

   // 也可以自定义读策略, 以适应不同的需求

   // 解析成功返回true.如果只有部分解析成功时虽然返回false,但已经解析成功的内容仍然可用

   // 如果宏XML_WITH_PARSE_STATUS设置为1(默认为0).可以从x.info()中得到解析器停止的位置,方便调试.但会降低解析器性能.

   x.parse( xml_reader( xml_string ) );

 

   xml x2;

   x2.push_back( xml::tag("root-x2") );    // 直接向空xml对象中添加标签

   x2("root-x2").push_back( xml::text("text value") );

   x2.write( cfile_writer( stderr ) );

    

   // 输出/root/node[prop]的值

   // ()运算符为标签查找,返回指定名称的第一个标签.[]运算符为属性查找,返回指定名称的属性.

   printf( "/root/node[prop] = [%s]\n", x("root")("node")["prop"].value().c_str() );

   // 这里使用了null object模式,所以无需检查每一步的返回结果,不会因为访问非法节点而产生异常.简化使用

   printf( "null object test:[%s]\n", x("roxxot")("noeede")["prop"].value().c_str() );

 

   // 把root标签转成其迭代器(&运算符)

   xml::tag_iterator root_tag = &x("root");

    

   // 迭代所有子节点

   for( xml::node_iterator node = x.root()->begin(); node != x.root()->end(); ++node ) {

       // xml::node_iterator为通用节点迭代器, 可以指向任何类型的节点.

       // 并可以转型成任意的其它迭代器. 但如果指向的节点类型和目标迭代器类型不符, 则会自动指向下一个合法的节点

       // 比如:

       //       这里有两个节点,一个abc标签,一个注释.

       //       如果有当前node迭代器指向abc标签.

       //            把node转成xml::tag_iterator类型时,则指向的节点不变.

       //            如果转成xml::comment_iterator时则会指向后面的注释.

       //            如果转成其它不存在类型的节点,则会指向容器的末尾.

       printf( "node type: %d\t", node->type );

       switch( node->type ) {

       case xml::_TYPE_TAG:

           printf( "tag name:%s\n", xml::tag_iterator(node)->name().c_str() );

           break;

       case xml::_TYPE_COMMENT:

           printf( "comment:%s\n", xml::comment_iterator(node)->text().c_str() );

           break;

       case xml::_TYPE_TEXT:

           printf( "text:%s\n", xml::text_iterator(node)->text().c_str() );

           break;

       case xml::_TYPE_ATTRIBUTE:

           printf( "attribute:%s=%s\n", xml::attribute_iterator(node)->name().c_str(), xml::attribute_iterator(node)->value().c_str() );

           break;

       default:

           printf( "unknown type\n" );

           break;

       }

   };

 

   // 迭代所有子标签

   for( xml::tag_iterator tag = x.root()->begin(); tag != x.root()->end(); ++tag ) {

       // 专用类型的迭代器只能遍历此类型的节点

       printf( "tag:%s\n", tag->name().c_str() );

   }

 

   // 在/root/node下添加abc标签, 并保存指向标签的迭代器

   xml::tag_iterator abc_tag = x("root")("node").push_back( xml::tag( "abc" ) );

   // 用abc_tag迭代器向abc标签添加属性

   abc_tag->push_back( xml::attribute( "tag-prop", "value abcdefg" ) );

   // 在abc标签前插入注释

   abc_tag->parent().insert( abc_tag, xml::comment( "tag-prop comment" ) );

   // 把xml_string解析出来,并将结果放到abc_tag所指向的标签里

   abc_tag->parse( xml_reader( xml_string ) );

   // 深拷贝x2对象中的根节点到abc标签中,实现跨xml对象进行节点复制

   abc_tag->push_front_copy( x2.root() );

   // 输出abc_tag指向的标签, 第二个参数true表示只输出内容标签的内容,不包含标签本身及属性

   abc_tag->write( cfile_writer( stdout ), true );

   // 删除第一个子节点

   abc_tag->erase( abc_tag->begin() );

   abc_tag->write( cfile_writer( stdout ), true );

   // 不能直接删除孙节点

   x.erase( xml::tag_iterator(abc_tag->begin()) );    // 转型成xml::tag_iterator是因为abc的第一个节点是属性.删除不直观.用标记会明显点

   abc_tag->write( cfile_writer( stdout ) );    // 没有删掉

   // 递归删除可以成功

   x.recursion_erase( xml::tag_iterator(abc_tag->begin()) );

   abc_tag->write( cfile_writer( stdout ) );    // 已经删除成功

   return 0;

}

只支持基本语法,很多东西不支持.比如:CDATA不支持,自定义转意也不支持...
用来做配置文件还是不错.

原文地址


本文转自Work Hard Work Smart博客园博客,原文链接:http://www.cnblogs.com/linlf03/archive/2013/01/03/2843273.html,如需转载请自行联系原作者

目录
相关文章
|
3月前
|
XML Web App开发 JavaScript
XML DOM 解析器
XML DOM 解析器
|
3月前
|
XML Web App开发 JavaScript
XML DOM 解析器
XML DOM 解析器
|
3月前
|
XML Web App开发 JavaScript
XML DOM 解析器
XML DOM 解析器
|
3月前
|
XML Web App开发 JavaScript
XML DOM 解析器
XML DOM 解析器
|
3月前
|
XML Web App开发 JavaScript
XML DOM 解析器
XML DOM 解析器
|
3月前
|
XML Java 数据格式
手动开发-简单的Spring基于XML配置的程序--源码解析
手动开发-简单的Spring基于XML配置的程序--源码解析
89 0
|
3月前
|
XML Web App开发 JavaScript
XML DOM 解析器
XML DOM 解析器
|
3月前
|
XML 前端开发 Java
讲解SSM的xml文件
本文详细介绍了SSM框架中的xml配置文件,包括springMVC.xml和applicationContext.xml,涉及组件扫描、数据源配置、事务管理、MyBatis集成以及Spring MVC的视图解析器配置。
89 1
|
5月前
|
XML Java 数据格式
Spring5入门到实战------7、IOC容器-Bean管理XML方式(外部属性文件)
这篇文章是Spring5框架的实战教程,主要介绍了如何在Spring的IOC容器中通过XML配置方式使用外部属性文件来管理Bean,特别是数据库连接池的配置。文章详细讲解了创建属性文件、引入属性文件到Spring配置、以及如何使用属性占位符来引用属性文件中的值。
Spring5入门到实战------7、IOC容器-Bean管理XML方式(外部属性文件)
|
2月前
|
XML Android开发 数据格式
Eclipse 创建 XML 文件
Eclipse 创建 XML 文件
33 2

推荐镜像

更多