c - 如何使用 libxml c 库获取 XML 中的属性?

标签 c xml xml-parsing libxml2

某项任务要求我解析一个 XML 文件并检查每个节点及其属性。我花了几周时间学习 XML 和 XML 解析。我什至在之前发布的与 C 中的 LIBXML 解析相关的问题的帮助下,基于这种理解,我在下面编写了这段代码。但是这段代码是有缺陷的,因为我没有达到目标。

我想我弄乱了一些父子和 sibling 的概念。 我从下面提到的 XML 文件中了解到的是:

Profile 是 Root 节点,Catalog 是它的子节点, 目录有 child 作为参数和 参数有 child 作为目标 并且所有目录节点都是彼此的 sibling 。

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

但是当我尝试通过将指针移动到目录子节点指针来从目录转到参数时,我无法进行。由于我无法达到参数,因此我无法到达目标。

希望对我的理解和代码进行更正。 P.S 我的要求是用 C 编写代码,所以请不要将我指向其他语言。

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

最佳答案

我最近对 ​​XML DOM 的理解工作正常,它说元素的所有属性在 DOM 中表示为该元素的子节点。所以,如果用上面的 XML 创建一个 DOM,我们将看到:

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

catalog2 和 catalog3 也将有他们的 child 。 基于此 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;
}

关于c - 如何使用 libxml c 库获取 XML 中的属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33709125/

相关文章:

c - 使用 PIC18 的 C18 库中的延迟函数进行长延迟

c++ - 当包含 SDL 时,简单的 tcp echo 程序不工作?

我可以将 SIGCONT 发送到正在运行的进程吗?

java - 如何使用命令行创建小型maven项目

Javascript 和 Titanium - 无法读取 XML 文本节点

javascript - 如何按元素内容过滤已解析的 XML 数据 [jQuery]

c - 使用C将BMP图像发送到串口

java - 如何在使用 JSOUP/JAVA 解析时保留原始字符串中的 "

android - RecyclerView 项目之间的差距很大

ios5 - 如何在 xcode 4.3 中使用 GDataXML 更改 xml 标记的值?