使用expat startelement handler C ++

时间:2010-09-23 13:34:56

标签: c++ variables global expat-parser

我使用expat来读取xml文件。我想从xml文件中指定的配置中填充一些我的类成员变量。我已经定义了我的startelement处理程序,

void Start(void *data,const XML_Char *el, const XML_Char **attr)

,这将引用如下:

XML_SetElementHandler(parser,Start, NULL);

目前我正在使用全局结构g_stConfigInfo来存储Start()

中的所有值

例如,

void Start(void *data,const XML_Char *el, const XML_Char **attr)
{
    if( _tcscmp(el,_T("blah"))==0 )
    {
        for (int i=0; attr[i]; i+=2)
        {
            if(_tcscmp(attr[i],_T("name"))==0)
            {
                g_stConfigInfo.sInputName = attr[i+1];
            }
            .........

然后我正在做myclass.sInputName = g_stConfigInfo.sInputname

我宁愿不使用全局变量,而是能够使其成为需要填充其成员变量的类的成员函数。  我不想在Start()中有这个类的实例。这样做的最佳方式是什么?

2 个答案:

答案 0 :(得分:1)

好吧,类成员函数就像常规函数一样,附加了隐式数据上下文。因此,如果您想避免引用全局数据,那么您必须将非NULL上下文参数传递给Start

习惯做法通常是这样的:

class MyHandler {
public:
    void Start(const XML_Char *el, const XML_Char **attr) {
        // ...dispatch on "el" here.
        // e.g. a map of strings to member function pointers
    }
};
...

template<T>
void
Start(void *data, const XML_Char *el, const XML_Char **attr)
{
    T *handler = static_cast<T*>(data);
    handler->Start(el, attr);
}

MyHandler handler;
XML_SetUserData(parser, handler);
XML_SetElementHandler(parser, Start<MyHandler>, NULL);

换句话说,如果你的类对应于某个XML元素,那么将它传递给处理函数是没有错的。

答案 1 :(得分:1)

之前我没有使用过Expat,但我认为使用XML_SetUserData就是你想要的。

class my_data
{
    public:
    static void start_callback(void *data, const XML_Char *el, const XML_Char **attr)
    {
        static_cast<my_data*>(data)->start(el, attr);
    }

    void start(const XML_Char *el, const XML_Char **attr);
};

//...
my_data data;
XML_SetUserData(parser, &data);
XML_SetElementHandler(parser, my_data::start_callback, NULL);

SetUserData将使解析器将您提供给它的指针传递给任何处理程序回调。 http://www.xml.com/pub/a/1999/09/expat/index.html?page=3#setuserdata