How to get attribute in XML using libxml c library?

A specific task requires me to parse an XML file and validate each node and its attributes. I spent several weeks studying XML and XML parsing. I even took advantage of earlier questions related to parsing LIBXML in C, and based on this understanding, I wrote this code below. But this code is wrong, as I am not achieving the goal.

I think I messed up the concept of parent child and sister. What I understand from the XML file below is as follows:

The profile is the root of the node, and the directory is its children, and there are children in the catalog as Parameters and the Parameter has children as Target and all the nodes in the catalog are siblings.

Profile--> Catalog--> Parameter-->Target
       |-> Catalog--> Parameter-->Target

But when I try to move from the Directory to the Parameter by moving the pointer to the directory children node pointer, I cannot go. And since I can’t reach the parameter I m, which cannot hit the target.

Thank you for the correction in my understanding and code. PS My requirement is to code in C, so please do not point me to another 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;
  }
+4
source share
1 answer

My recent understanding of the XML DOM is working fine, and it says that all attributes of an element are represented in the DOM as child nodes of that element. So, if we make the DOM above XML, we will see:

                            Profile
   ___________________________|____________________
  |        |         |        |          |         |
 date    origin   version   catalog1  catalog2   catalog3
    __________________________|
   |              |           |
parameter    version         id
   |_________________________________________
   |         |        |           |          |
  name      value   applytype    reboot     target
                                    __________|
                                   |          |
                              instance      class

2 3 . DOM, get_next_node get_children_node, .

/**
 * 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;
}
+3

Source: https://habr.com/ru/post/1615883/


All Articles