elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Trabajando con las ramas de git (tercera parte)


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  Parseo de XML con libxml2
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Parseo de XML con libxml2  (Leído 2,591 veces)
jdomgo3

Desconectado Desconectado

Mensajes: 22


Ver Perfil
Parseo de XML con libxml2
« en: 12 Enero 2014, 22:44 pm »

Saludos a todos.

Estoy usando por primera vez la librería libxml y la verdad, estoy bastante perdido, he visto que hay muchos ejemplos pero no hay una explicación "decente" sobre el uso de la librería, o al menos no llego a comprender cómo se utiliza con cierta lógica. Tengo el siguiente archivo:

Código
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <serverindex:ServerIndex xmi:version="2.0" xmi:id="ServerIndex_1" hostName="localhost.localdomain">
  3.  <serverEntries xmi:id="ServerEntry_1385929332571" serverDisplayName="nodeagent" serverName="nodeagent" serverType="NODE_AGENT">
  4.    <specialEndpoints xmi:id="NamedEndPoint_1385929332578" endPointName="BOOTSTRAP_ADDRESS">
  5.      <endPoint xmi:id="EndPoint_1385929332571" host="localhost.localdomain" port="2809"/>
  6.    </specialEndpoints>
  7.  </serverEntries>
  8.  <serverEntries xmi:id="ServerEntry_1385932589812" serverName="LTEST003_MULT_T03_10" serverType="APPLICATION_SERVER">
  9.    <deployedApplications>commsvc.ear/deployments/commsvc</deployedApplications>
  10.    <deployedApplications>ibmasyncrsp.ear/deployments/ibmasyncrsp</deployedApplications>
  11.    <specialEndpoints xmi:id="NamedEndPoint_1385932589812" endPointName="BOOTSTRAP_ADDRESS">
  12.      <endPoint xmi:id="EndPoint_1385932589812" host="localhost.localdomain" port="48012"/>
  13.    </specialEndpoints>
  14.  </serverEntries>
  15.  <serverEntries xmi:id="ServerEntry_1385932595602" serverName="LTEST003_MULT_T03_20" serverType="APPLICATION_SERVER">
  16.    <deployedApplications>commsvc.ear/deployments/commsvc</deployedApplications>
  17.    <deployedApplications>ibmasyncrsp.ear/deployments/ibmasyncrsp</deployedApplications>
  18.    <specialEndpoints xmi:id="NamedEndPoint_1385932595602" endPointName="BOOTSTRAP_ADDRESS">
  19.      <endPoint xmi:id="EndPoint_1385932595602" host="localhost.localdomain" port="48030"/>
  20.    </specialEndpoints>
  21.    <specialEndpoints xmi:id="NamedEndPoint_1385932595603" endPointName="SOAP_CONNECTOR_ADDRESS">
  22.      <endPoint xmi:id="EndPoint_1385932595603" host="localhost.localdomain" port="48031"/>
  23.    </specialEndpoints>
  24.  </serverEntries>
  25. </serverindex:ServerIndex>

Es una versión muy reducida del original, lo he recortado por que no tiene sentido que os ponga un archivo de 2000 líneas aquí. El caso es que he compilado el siguiente código para que me saque el nombre del nodo de cada uno de los nodos desde arriaba hasta abajo:

Código
  1. #include <stdio.h>
  2. #include <libxml/parser.h>
  3. #include <libxml/tree.h>
  4.  
  5. static void print_element_names(xmlNode *a_node)
  6. {
  7. xmlNode *cur_node = NULL;
  8. for (cur_node = a_node; cur_node; cur_node = cur_node->next) {
  9. if (cur_node->type == XML_ELEMENT_NODE) {
  10. printf("%s\n", cur_node->name);
  11. }
  12. print_element_names(cur_node->children);
  13. }
  14. }
  15.  
  16. int main()
  17. {
  18. xmlDoc *doc = NULL;
  19. xmlNode *root_element = NULL;
  20. const char *Filename = "docs/archivo.xml";
  21. doc = xmlReadFile(Filename, NULL, 0);
  22. if (doc == NULL)
  23. {
  24. printf("ERROR: No se puede parsear el archivo %s\n", Filename);
  25. } else {
  26. root_element = xmlDocGetRootElement(doc);
  27. print_element_names(root_element);
  28. xmlFreeDoc(doc);;
  29. }
  30. xmlCleanupParser();
  31. return (0);
  32. }

Y funcionar funciona, lo que saca es una lista con los nombres de cada nodo:

Código
  1. ServerIndex
  2. serverEntries
  3. specialEndpoints
  4. endPoint
  5. serverEntries
  6. deployedApplications
  7. deployedApplications
  8. specialEndpoints
  9. endPoint
  10. serverEntries
  11. deployedApplications
  12. deployedApplications
  13. specialEndpoints
  14. endPoint
  15. specialEndpoints
  16. endPoint

Me gustaría aprender a usar bien esta librería para poder imprimir a mi antojo no solo los nombres de ls nodos, si no imprimir solo los que me interesen en función de determinadas características como el valor de alguna propiedad del nodo como "serverType" por ejemplo. He probado con comparación de cadenas mediante strcmp de la librería string.h, pero no se muy bien el formato o el tratamiento de formatos que tiene libxml, ya que no me funciona con las pruebas que he realizado.

Me gustaría saber si hay alguien que tiene experiencia con libxml, y en caso de haber alguien si estaría dispuesto a explicarme algunas dudas sobre cómo hacer algunos parseos.

Un saludo y gracias de antemano.


En línea

ivancea96


Desconectado Desconectado

Mensajes: 3.412


ASMático


Ver Perfil WWW
Re: Parseo de XML con libxml2
« Respuesta #1 en: 12 Enero 2014, 23:13 pm »

Nunca usé esa librería, y quizás no te parezca un comentario muy constructivo, pero si necesitas hacer lo que dices, podrías hacer a mano las funciones, no parece difícil.


En línea

jdomgo3

Desconectado Desconectado

Mensajes: 22


Ver Perfil
Re: Parseo de XML con libxml2
« Respuesta #2 en: 13 Enero 2014, 07:31 am »

Nunca usé esa librería, y quizás no te parezca un comentario muy constructivo, pero si necesitas hacer lo que dices, podrías hacer a mano las funciones, no parece difícil.

Muchas gracias por tu rápida respuesta ivancea96, en realidad uso una función print_element_names en el ejemplo que he puesto, pero creo que ya se a que te refieres, supongo que dices que haga una función para cada típo de parseo que necesito. El problema no lo tengo en hacer funciones, si no en la manera de usar los diferentes módulos de la librería libxml, que no se ni cuantos son, ni para que sirven ni cómo se manejan. En la documentación de la librería no viene muy bien explicado. Por ejemplo, supongamos que quiero comparar cadenas, he probado a hacerlo así:

Código
  1. #include <string.h>
  2.  
  3. #define JVMTAG "serverEntries"
  4.  
  5. ...
  6.  
  7. if (cur_node->type == XML_ELEMENT_NODE) {
  8. if(!strcmp(JVMTAG,cur_node->name)){
  9. printf("%s\n", cur_node->name);
  10. }
  11. }

Pero no puede, me devuelve el siguiente warning:

Código
  1. passing 'const xmlChar *' (aka 'const unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]

¿Alguna idea?
En línea

jdomgo3

Desconectado Desconectado

Mensajes: 22


Ver Perfil
Re: Parseo de XML con libxml2
« Respuesta #3 en: 20 Enero 2014, 22:27 pm »

Saludos de nuevo, ya he conseguido averiguar cómo funciona mas o menos la librería libxml2, a base de darme cabezazos y probar una y otra vez con la poca/escasa información que hay por ahí. Aquí va el código, he puesto comentarios de lo que he hecho en la función "print_element_names", espero que se entienda:

Código
  1. #include <stdio.h>
  2. #include <libxml/parser.h>
  3. #include <libxml/tree.h>
  4.  
  5. static void print_element_names(xmlNode *a_node)
  6. {
  7. xmlNode *cur_node = NULL;
  8. for (cur_node = a_node; cur_node; cur_node = cur_node->next) {
  9. if (cur_node->type == XML_ELEMENT_NODE) {
  10.  
  11. /* Con este if me quedo solo con los nodos
  12. que contienen el string "serverEntries" */
  13. if (!xmlStrcmp(cur_node->name, (const xmlChar *) "serverEntries")) {
  14.  
  15. /* Con este for parseo cada uno de los atributos
  16. o propiedades de cada nodo, uno a uno, lo convierto
  17. a string y lo almaceno en una variable llamada value */
  18. for(xmlAttrPtr attr = cur_node->properties; NULL != attr; attr = attr->next) {
  19. xmlChar* value = xmlNodeListGetString(cur_node->doc, attr->children, 1);
  20.  
  21. /* Finalmente comparo el nombre del atributo de cada
  22. vuelta del bucle, y si coincide con el string "serverName"
  23. pinto solo el valor */
  24. if (!xmlStrcmp(attr->name, (const xmlChar *) "serverName")) {
  25. printf("%s\n",value);
  26. }
  27. }
  28. }
  29. }
  30. print_element_names(cur_node->children);
  31. }
  32. }
  33.  
  34. int main()
  35. {
  36. xmlDoc *doc = NULL;
  37. xmlNode *root_element = NULL;
  38. const char *Filename = "docs/serverindex.xml";
  39. doc = xmlReadFile(Filename, NULL, 0);
  40. if (doc == NULL)
  41. {
  42. printf("ERROR: No se puede parsear el archivo %s\n", Filename);
  43. } else {
  44. root_element = xmlDocGetRootElement(doc);
  45. print_element_names(root_element);
  46. xmlFreeDoc(doc);;
  47. }
  48. xmlCleanupParser();
  49. return (0);
  50. }

Aún así, como no he experimentado mucho con esta librería, me gustaría que alguien que la controle mejor me dijera si lo que estoy haciendo es la mejor manera, por que no se por que me da que igual se puede simplificar mucho mas y mejor.

Un saludo y gracias de antemano.
« Última modificación: 20 Enero 2014, 22:30 pm por jdomgo3 » En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
Parseo + GD
PHP
multi-media asdfg 3 2,781 Último mensaje 8 Agosto 2011, 23:00 pm
por multi-media asdfg
Consulta; TinyMCE parseo de HTML
Desarrollo Web
astinx 0 1,768 Último mensaje 22 Julio 2012, 02:02 am
por astinx
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines