理解DOM树能更好的理解libxml函数操作原理。只要理解的,才是深刻的,能做到知其然而知其所以然,使用函数时心里有底而且不易出错。为了大家更好理解DOM树在内存中的构造,我特地写了一个典型XML文件(dom.xml),并且画出其DOM树内存构造图。其后提供了一个不用XML库,查找XML节点和属性的通用程序(dom_xml.c),此程序具有较好的实用性。
1.dom.xml文件
dom.xml文件内容如下:
FmtDesc="dxpt fmt" Fmttype="string">
2.dom.xml形成的DOM树
xmlNode(Format)表示这片内存空间类型为xmlNode, 元素名称为Format。
xmlNodePtr为xmlNode *的重定义,即xmlNode的指针重定义。
下图20-1形象的说明dom.xml在内存中如何形成DOM树的。
图20-1 DOM树实例图
3.得到XML节点和属性的通用程序
dom_xml.c源代码如下:
#include
#include
#include
#include
#include
#include
#include
#include
#include
/*项目中数字最好用宏代替*/
struct XML_attr {
char attr_name[30+1] ;
char attr_value[100+1] ;
} ;
struct XML_node{
char node_name[30+1] ;
char node_value[100+1] ;
} ;
/*------------------------------------------------------------------------
* Function Name : get_xml_attr
* Description : 得到节点的所有属性
* Input : node_ptr -- 当前节点
* : xml_attr -- 存储属性名称和属性值
* : maxnum -- 最大属性个数
*Output : xml_attr -- 存储属性名称和属性值
* Return : 0 -- Success
* -1 -- Failure
*------------------------------------------------------------------------*/
int get_xml_attr( xmlNodePtr node_ptr, struct XML_attr xml_attr[], int maxnum)
{
xmlAttr *attr;
int i = 0;
attr = node_ptr->properties;
while( attr != NULL ) {
if ( attr->children == NULL ) {
attr = attr->next;
continue;
}
strncpy( xml_attr[i].attr_name, ( char * )attr->name, 30 );
strncpy( xml_attr[i].attr_value, ( char * )attr->children->content, 100 );
attr = attr->next;
i++ ;
if ( i > maxnum)
{
printf("xml attr over limit num\n");
return -1 ;
}
}
return 0 ;
}
/*------------------------------------------------------------------------
* Function Name : get_xml_node
* Description : 得到节点的所有属性
* Input : node_ptr -- 当前节点
* : xml_node -- 存储元素名称和值
* : maxnum -- 最大元素个数
*Output : xml_node -- 存储元素名称和值
* Return : 0 -- Success
* -1 -- Failure
*------------------------------------------------------------------------*/
int get_xml_node( xmlNodePtr node_ptr, struct XML_node xml_node[], int maxnum)
{
xmlNodePtr cur;
int i = 0;
cur = node_ptr->children;
while( cur != NULL ) {
if ( cur->children == NULL ) {
cur = cur->next;
continue;
}
strncpy( xml_node[i].node_name, ( char * )cur->name, 30 );
strncpy( xml_node[i].node_value, ( char * )cur->children->content, 100 );
cur = cur->next;
i++ ;
if ( i > maxnum)
{
printf("xml node over limit num\n");
return -1 ;
}
}
return 0 ;
}
/*
* Function Name: get_xml_node_ptr
* Description : 获取子节点指针
* Input : node_ptr -- 结点指针
* : node_name -- 结点名
* Output : node_ptr -- 子节点指针
* Return : 0 -- Success
* -1 -- Failure
*/
int get_xml_node_ptr( xmlNodePtr node_ptr , char *node_name )
{
xmlNodePtr cur;
cur = node_ptr;
while( cur != NULL ) {
if( ( xmlStrcmp( cur->name, node_name ) ) == 0 )
{
break;
}
else
cur = cur->next;
}
if( cur == NULL ) {
return -1;
}
node_ptr = cur;
return 0 ;
}
int main()
{
char value[128];
int ret;
int i ;
xmlDocPtr doc;
xmlNodePtr cur;
xmlNodePtr attr;
xmlNodePtr node;
struct XML_attr fmt_attr[3] ;
struct XML_node meta_node[3] ;
memset(fmt_attr, 0x00, sizeof(fmt_attr)) ;
memset(meta_node, 0x00, sizeof(meta_node)) ;
doc = xmlParseFile("dom.xml");
if (doc == NULL ) {
fprintf(stderr,"Document not parsed successfully. \n");
return (-1);
}
cur = xmlDocGetRootElement(doc);
if (cur == NULL) {
fprintf(stderr,"empty document\n");
xmlFreeDoc(doc);
return (-1);
}
attr = cur ;
ret=get_xml_attr(attr, fmt_attr, 3) ;
assert(!ret);
for(i=0; i<3; i++)
{
printf("attr_name[%d]=%s, attr_value[%d]=%s\n",i,fmt_attr[i].attr_name,i,fmt_attr[i].attr_value);
}
node=cur->children ;
ret = get_xml_node_ptr( node , "meta" ) ;
assert(!ret);
node=cur->children->next ;
ret =get_xml_node(node, meta_node, 3) ;
assert(!ret);
for(i=0; i<3; i++)
{
printf("node_name[%d]=%s, node_value[%d]=%s\n",i,meta_node[i].node_name,i,meta_node[i].node_value);
}
xmlFreeDoc(doc);
return 0;
}
编译 gcc dom_xml.c -o dom_xml -I/usr/local/include/libxml2 -lxml2。
执行 ./dom_xml,执行结果如下:
attr_name[0]=FmtName, attr_value[0]=FMT_DXPT_DX0001_IN
attr_name[1]=FmtDesc, attr_value[1]=dxpt fmt
attr_name[2]=Fmttype, attr_value[2]=string
node_name[0]=hello, node_value[0]=first
node_name[1]=good, node_value[1]=second
node_name[2]=gold, node_value[2]=third
摘录自《深入浅出Linux工具与编程》