前段时间有个华为项目需要添加一个天气预报应用。于是埋头一个月搞出了一个可用版本。技术实现上分三大步骤,第一步是和天气网站www.accuweather.com建立socket连接,第二步是将XML数据格式中的有用信息解析出来,最后将数据以图片UI的形式展现给用户。这次先讲如何解析XML数据,下次再说说Socket连接。
1. 主要使用的API
MTK平台有一套解析XML的API,在xml_def.h文件里可以看到这些函数的定义。主要的几个API如下所示:
/* this function is used as default element start handler */
void xml_elem_start_hdlr( void *data, const kal_char *el,
const kal_char **attr, kal_int32 error);
/* this function is used as default element end handler */
void xml_elem_end_hdlr(void *data, const kal_char *el, kal_int32 error);
/* this function is used to register element handler*/
void xml_register_element_handler( XML_PARSER_STRUCT *parser,
XML_start_elem_hdlr start_hdlr, XML_end_elem_hdlr end_hdlr);
/*this function is used to register data handler*/
void xml_register_data_handler(XML_PARSER_STRUCT *parser, XML_data_hdlr data_hdlr);
2. 示例代码
下面给出的这段数据是请求城市列表得到的XML数据:
<?xml version="1.0" encoding="utf-8" ?>
<adc_database xmlns="http://www.accuweather.com">
<citylist us="0" intl="2" extra_cities="0">
<location cnt="1" city="Beijing" state="China (Beijing)" location="cityId:101924" />
<location cnt="2" city="Beijing" state="China (Shanxi)" location="cityId:76101" />
</citylist>
<copyright>Copyright 2011 AccuWeather.com</copyright>
<use>This document is intended only for use by authorized licensees of AccuWeather.com. Unauthorized use is prohibited. All Rights Reserved.</use>
<product>huawei</product>
<redistribution>Redistribution Prohibited.</redistribution>
</adc_database>
通过上面这段数据来说明程序是如何将里面有用的信息解析出来的。
我们先注册解析XML结点的各种函数,包括解析结点前的函数,解析结点完成后的函数,以及解析数据的函数。
xml_register_element_handler(xml_parser,
accuweather_city_xml_start_element_hdlr,
accuweather_city_xml_end_element_hdlr);
xml_register_data_handler(xml_parser, accuweather_city_xml_data_hdlr);
元素结点不光有数据值,还有各种属性。比如上面的citylist和location结点就有几个属性值,product结点只有数据值。将属性值提取出来的操作可以放在解析结点开始的注册函数里面。如上面的accuweather_city_xml_start_element_hdlr函数的具体实现如下:
#define ACCUWEATHER_XML_CITYLIST "citylist"
static void accuweather_city_xml_start_element_hdlr(void *not_use, const char *el, const char **attr, int error)
{
if (!strcmp(el, ACCUWEATHER_XML_CITYLIST))
{
/* attr[1]: num of cities in USA, attr[3]&attr[5]: num of other cities */
g_cntx_accu.city_list_xml.city_num= atoi(attr[1]) + atoi(attr[3]) + atoi(attr[5]);
if(!g_cntx_accu.city_list_xml.city_num)
{
return;
}
g_cntx_accu.city_list_xml.city_list = (accu_city_xml *)OslMalloc( sizeof(accu_city_xml) * g_cntx_accu.city_list_xml.city_num );
}
……
}
上面这段代码就是计算出citylist里面叫名称叫Beijing的城市有多少个。attr[0]的值为us,attr[1]的值为0,attr[2]的值为intel,attr[3]的值为2。通过这样的方式我们提取出XML数据的属性值。
解析完结点后我们不需要做别的操作,所以accuweather_city_xml_end_element_hdlr函数可以写成一个空函数。
遇到结点数据后系统会调用注册的解析数据函数accuweather_city_xml_data_hdlr来提取数据项。此函数的具体实现如下:
#define ACCUWEATHER_XML_PRODUCT "product"
static void accuweather_city_xml_data_hdlr(void *not_use, const char *el, const char *value, int len, int error)
{
if (!strcmp(el, ACCUWEATHER_XML_ PRODUCT))
{
gui_printf("Product = %s/n", value);
}
}
这样就会打印出来“Product=huawei”这个字串。结点数据值会存放在value指针所指向的字串中,若是要将value的值转换成整形数的话,可以使用atoi函数。
通过上述介绍的方法同样可以轻松解析出XML中的天气数据。
3. 注意事项
程序如何将要解析的XML数据段传入有两种方法,一种是传入XML文件数据,一种是传入buffer数据。对应的的API如下:
kal_int32 xml_parse(XML_PARSER_STRUCT *parser, kal_wchar *file_name);
kal_int32 xml_parse_buffer(XML_PARSER_STRUCT *parser, const kal_char *xmltext, kal_int32 length);