自己写的简单xml解析器

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

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



已经在很多正式,非正式的场合用过了.干脆开源得了.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,如需转载请自行联系原作者

目录
打赏
0
0
0
0
49
分享
相关文章
手动开发-简单的Spring基于XML配置的程序--源码解析
手动开发-简单的Spring基于XML配置的程序--源码解析
89 0
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
92 2
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性。 行为型模式分为: • 模板方法模式 • 策略模式 • 命令模式 • 职责链模式 • 状态模式 • 观察者模式 • 中介者模式 • 迭代器模式 • 访问者模式 • 备忘录模式 • 解释器模式
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
结构型模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者釆用组合或聚合来组合对象。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象结构型模式比类结构型模式具有更大的灵活性。 结构型模式分为以下 7 种: • 代理模式 • 适配器模式 • 装饰者模式 • 桥接模式 • 外观模式 • 组合模式 • 享元模式
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析

推荐镜像

更多
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等