1

我正在使用 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() 中有这个类的实例。这样做的最佳方法是什么?

4

2 回答 2

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

于 2010-09-23T14:04:49.830 回答
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 元素,那么将它传递给处理函数并没有错。

于 2010-09-23T13:42:32.817 回答