Properties --- C++读配置信息的类(三)

这篇博客介绍了如何使用C++实现XMLProps类来读取符合特定XML格式的配置信息。文章详细展示了XML配置文件的结构,以及XMLPropsLoad类的实现,该类利用开源的xml2库进行XML解析。通过XMLPropsLoad::operator() 方法,将XML配置文件的内容加载到PropMap中。最后,给出了测试程序tst-xmlprops.cpp的示例,用于验证XMLProps类的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本篇在前两篇的基础上,进一步给出XML格式文件装载的Properties类的实现。如前所述,正是因为我们将Properties设计成为一个模版类,使得装载的过程和方式称为模版的参数,使得Properties成为一个可以适应装载不同方式和格式的配置文件信息的实用类。在前一篇,我们实现了ini文件格式的装载。本篇我们来实现xml格式的装载。

首先来说明一下我们规定的xml的格式。下面是一个实际的xml格式的配置属性信息内容,文件名称为 props.xml:

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd" >

<prop>
<node01>
       <comment>node01 configure</comment>
       <entry key="host">127.0.0.1</entry>
       <entry key="port">3001</entry>
       <entry key="nodeid">101-12345</entry>
       <entry key="acno">100000000000</entry>
       <entry key="teller">Auter01</entry>
       <entry key="market">201</entry>
       <entry key="quantity">1234</entry>
       <entry key="ctimeout">6000</entry>
</node01>

<node02>
       <comment>node02 configue</comment>,
       <entry key="host">127.0.0.1</entry>
       <entry key="port">3002</entry>
       <entry key="nodeid">102-12345</entry>
       <entry key="acno">100000000000</entry>
       <entry key="teller">Auter02</entry>
       <entry key="market">201</entry>
       <entry key="quantity">1234</entry>
       <entry key="ctimeout">6000</entry>
</node02>

</prop>

 

 

在上面的内容中,根结点prop只是表示一个xml数据的开始。第二层结点为Properties的Section名称。第三层结点中的entry名称的结点为各个属性结点。其中的key属性的值为Properties的关键字名称,结点的实际内容为对应这个这个关键字的实际的值。

现在,我们来实现对上面格式的xml文件的装载实现。如IniProps的实现一样,我们首先定义一个XMLProps的类。下面是这个类的定义头文件 xtl/XMLProps.h:

 

1
2 /* xtl/XMLProps.h
3   Author: ZhangTao
4   Date: Nov 6, 2008
5 */
6
7 # ifndef XMLProps_h
8 # define XMLProps_h
9
10 # include       "xtl/Properties.h"
11
12 namespace xtl  {
13
14 class XMLPropsLoad  {
15   public:
16     void operator() (PropMap& props, std::istream& is, const char* section);
17 };
18
19 typedef Properties<XMLPropsLoad> XMLProps;
20
21 const char* const XML_ENTRY = "entry";          // Property node entry name
22 const char* const XML_KEY = "key";              // Property key name
23 const char* const DEFAULT_SECTION = "default";  // default section
24
25 } // end of <namespace xtl>
26
27 # endif /* end of <ifndef XMLPropsLoad_h> */
28

 

 

与上一篇的xtl/iniProps.h内容比较,可以看出,除了类的名称外,它们的内容几乎相同。在21行到23行定义了三个常量,用于装载函数中使用。比较上面的xml内容,可以看出XML_ENTRY对应的是属性结点的名称;XML_KEY对应的是关键字的xml结点属性名称。DEFAULT_SECTION是定义了缺省的属性部的名称。

实现的文件名称为 XMLPropsLoad.cpp。其中使用了开源的xml2的函数库作为xml的解析工具。内容如下:

 

 

  1 /* XMLProps.cpp
  2   Author: ZhangTao
  3   Date: Nov 6, 2008
  4 */
  5
  6 # include       <sstream>
  7
  8 # include       "libxml/parser.h"
  9 # include       "xtl/utilfunc.h"
10 # include       "xtl/XMLProps.h"
11
12 namespace xtl {
13
14 DeclareThisFile;
15
16 void XMLPropsLoad::operator() (PropMap& props, std::istream& is,
17                 const char* section)
18 {
19   std::stringstream  iss;
20
21   iss << is.rdbuf();
22
23   const std::string& xmlStr = iss.str();
24
25   xmlDocPtr xdoc = xmlReadMemory(xmlStr.c_str(), xmlStr.size(), "Prop",  0, 0);
26
27   if ( xdoc == 0 )
28     ThrowUtilExceptWithSource("Invalid XML stream", "");
29
30   // goto root level
31   xmlNodePtr curNode = xmlDocGetRootElement(xdoc);
32
33   // goto <section> level
34   if ( (curNode == 0) || ((curNode = curNode->xmlChildrenNode) == 0) )
35     ThrowUtilExceptWithSource("Empty XML stream", "");
36
37
38   if ( isEmptyStr(section) )
39     section = DEFAULT_SECTION;
40
41   while( (curNode != 0) && (xmlStrcmp(curNode->name,
42         (const xmlChar*)section) != 0) )
43     curNode = curNode->next;
44
45   if ( curNode == 0 )
46     ThrowUtilExceptWithSource("can not found <%s> node", section);
47
48   // goto <Property> level
49   curNode = curNode->xmlChildrenNode;
50
51   while( curNode != 0 )      {
52     if ( xmlStrcmp(curNode->name, (const xmlChar*)XML_ENTRY) == 0 )    {
53       xmlChar* key = xmlGetProp(curNode, (const xmlChar*)XML_KEY);
54       xmlChar* val = xmlNodeGetContent(curNode);
55
56       props.insert(make_pair(std::string((const char*)key),
57                         std::string((const char*)val)));
58       xmlFree(key);
59       xmlFree(val);
60     }
61     curNode = curNode->next;
62   }
63 }
64
65 } // end of <namespace stl>
66

 

 

这里19行定义了一个字串流。21行通过输入流的rdbuf调用将输入流参数的内容读入到了字串流。通过字串流得到一个string类,从而又可以得到一个C字符串内容,满足了xml库读入内容的解析函数xmlReadMemory的参数要求。这些都属于C++标准库的操作,可以参考C++的有关输入输出流部分。接下来的过程便是xml解析函数的操作。56行是得到有关的属性值对后的插入操作。

同样的,我们编写一个测试程序tst-xmlprops.cpp如下:

 

 

# include       "xtl/XMLProps.h"

int
main(int argc, char* argv[])
{
  const char* sec;

  if ( argc > 1 )
    sec = argv[1];
  else
    sec = "";

  xtl::XMLProps prop(std::cin, sec);

  prop.list(std::cout);

  if ( argc > 2 )
    std::cout << "Key:<" << argv[2] << "> Value:" <<
                prop.getProperty(argv[2]) << "/n";

  return 0;
}

 

 

编译成目标码 tst-xmlprops,使用上面的xml文件作为测试内容。

 

# ./tst-xmlprops node01 port <props.xml
acno = 100000000000
ctimeout = 6000
host = 127.0.0.1
market = 201
nodeid = 101-12345
port = 3001
quantity = 1234
teller = Auter01
Key:<port> Value:3001

 

 

至此,大功告成。

下一篇,将介绍一个Properties类的应用实例。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值