Reputation: 433
A certain task requires me to parse an XML file and check every node and its attributes. I have spent few weeks learning XML and XML parsing. I have even taken the help of earlier questions posted related to LIBXML parsing in C and based on that understanding I have written this code below. But this code is flawed as I doesn't achieve the objective.
I think I have messed up some parent child and sibling concept. What i understand from the below mentioned XML file is that:
Profile is the Root node and Catalog's are its children and Catalog has children as Parameters and Parameter has children as Target and all catalog nodes are each other siblings.
Profile--> Catalog--> Parameter-->Target
|-> Catalog--> Parameter-->Target
But when i try to go from Catalog to Parameter by moving the pointer to Catalogs children node pointer, I m not able to go. And as i m not able to reach Parameter I m not able to go to target.
Would appreciate correction in my understanding and Code. P.S My requirement is to code in C, so please don't point me to other language.
/***** MY XML FILE ***************************/
<?xml version="1.0" encoding="UTF-8"?>
<!-- When VIOS level changes, the value of ioslevel needs to change manually -->
<Profile origin="get" version="3.0.0" date="2012-10-05T00:00:00Z">
<Catalog1 id="devParam" version="3.0">
<Parameter1 name="policy" value="single" applyType="boot" reboot="true">
<Target1 class="device" instance="disk1"/>
</Parameter1>
</Catalog1>
<Catalog2 id="devParam" version="3.0">
<Parameter2 name="policy" value="no" applyType="boot">
<Target2 class="device" instance="disk2"/>
</Parameter2>
</Catalog2>
<Catalog3 id="devParam" version="3.0">
<Parameter3 name="policy" value="no" applyType="nextboot" reboot="true">
<Target3 class="device" instance="disk3"/>
</Parameter3>
</Catalog3>
</Profile>
/****************************************************************/
#include <string.h>
#include <stdio.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
static void print_element_names(xmlDoc *doc, xmlNode * profile_node)
{
xmlNode *catalog_node = NULL, *parameter_node = NULL, *target_node = NULL, *tmp_node = NULL;
xmlChar *instance=NULL, *key=NULL;
if (xmlStrcmp(profile_node->name, (const xmlChar *) "Profile")) {
fprintf(stderr,"document of the wrong type, root node != story");
xmlFreeDoc(doc);
return;
}
for (catalog_node = profile_node->xmlChildrenNode; catalog_node; catalog_node =catalog_node->next)
{
if (catalog_node->type == XML_ELEMENT_NODE)
{
printf("Catalog %s \t type %d \n",catalog_node->name, catalog_node->type);
for(parameter_node = catalog_node->xmlChildrenNode; parameter_node; parameter_node = parameter_node->next)
{
if (parameter_node->type == XML_ELEMENT_NODE)
{
printf("Parameter %s \t type %d \n",parameter_node->name, parameter_node->type);
for( target_node=parameter_node->xmlChildrenNode->next; target_node; target_node=target_node->next)
{
printf("Target %s \t type %d \t",target_node->name, target_node->type);
if((target_node->type == XML_ELEMENT_NODE)&&(!strcmp(target_node->name, (const xmlChar *)"Target")))
{
instance_attr = xmlGetProp(inner_child, "instance");
printf("instance_attr = %s\n",instance_attr);
}
}
}
}
}
}
}
int main(int argc, char **argv)
{
xmlDoc *doc = NULL;
xmlNode *root_element = NULL;
if (argc != 2) return(1);
/*parse the file and get the DOM */
if ((doc = xmlReadFile(argv[1], NULL, 0)) == NULL){
printf("error: could not parse file %s\n", argv[1]);
exit(-1);
}
/*Get the root element node */
root_element = xmlDocGetRootElement(doc);
print_element_names(doc, root_element);
xmlFreeDoc(doc); /* free document*/
xmlCleanupParser(); /*/ Free globals*/
return 0;
}
Upvotes: 5
Views: 2995
Reputation: 433
My recent understanding of XML DOM is working fine and it says that all the attributes of an element are represented in DOM as a children nodes of that element. So, if make a DOM of above XML we will see:
Profile
___________________________|____________________
| | | | | |
date origin version catalog1 catalog2 catalog3
__________________________|
| | |
parameter version id
|_________________________________________
| | | | |
name value applytype reboot target
__________|
| |
instance class
And catalog2 and catalog3 will also be having their children. Based on this DOM if i have written get_next_node and get_children_node function and it is working fine for me.
/**
* get the children node and skip any non xml element node
*
* @param xml node
* @param xml children node
*
* @return xmlNodePtr children of xml node
*/
static void xmlGetNodeChildren(xmlNodePtr xmlNode, xmlNodePtr *childrenNode)
{
xmlNodePtr node = NULL;
node = xmlNode->children;
while (node->type != XML_ELEMENT_NODE)
{
node = node->next;
if (node == NULL)
{
break;
}
}
*childrenNode = node;
}
/**
* get the next node and skip any non xml element node
* such as text and comment node
*
* @param xml node
* @param xml next node
*/
static void xmlGetNodeNext(xmlNodePtr *xmlNode)
{
xmlNodePtr node = NULL;
node = (*xmlNode)->next;
while (node->type != XML_ELEMENT_NODE)
{
node=node->next;
if (node == NULL)
{
break;
}
}
*xmlNode = node;
}
Upvotes: 3