• Publicidad

Elementos duplicados en un XML

¿Apenas comienzas con Perl? En este foro podrás encontrar y hacer preguntas básicas de Perl con respuestas aptas a tu nivel.

Elementos duplicados en un XML

Notapor sergiarcano » 2012-11-28 10:40 @486

Hola a todos. Acabo de empezar en esto del Perl y he tirado varias veces de los tutoriales y algunos mensajes en el Foro para ver cosas, pero ahora ando perdido con algo porque no entiendo el comportamiento de una estructura con la que estoy pegándome; a ver si me podéis ayudar.

Tengo un xml con una serie de servicios para unas llamadas HTTP que tengo que hacer. El script ya está hecho y funciona, pero me han pedido que añada un par de funcionalidades. Una de ellas es revisar si dentro del xml hay dos servicios iguales y, en este caso, mostrar un error y salir. El xml se carga en una estructura tipo hash (la cual reconozco que no soy capaz de "dibujar" en mi cabeza para entenderla bien) y, a partir de ahí, se usa un array también. Finalmente en la estructura principal recorro las claves que son los servicios (en este caso serían "test", "alive" y "memory"). He tratado de aplicar lo que previamente había probado en un script que he hecho aparte a modo de prueba:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. my @duplicateArray;
  2. my $countDuplicateArray = 0;
  3.  
  4. foreach (@xmlArray) {
  5.     foreach ( keys( %{$_} ) ) {
  6.         chomp($_);
  7.         if ( ( $_ =~ /^$serviceName/ ) || uc($serviceName) eq "ALL" ) {
  8.             print "=" x 80, "\n";
  9.  
  10.             # If service is duplicated in xml, print error and exits.
  11.             if ( grep ( $_, @duplicateArray ) ) {
  12.                 print( STDERR "Error : Service $_ duplicated in XML configuration file\n" );
  13.                 $log->log( "Service $_ duplicated in XML configuration file", 1 );
  14.  
  15.                 #exit(1);
  16.             }
  17.             else {
  18.                 $duplicateArray[$countDuplicateArray] = $_;
  19.                 $countDuplicateArray++;
  20.             }
  21.  
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


Tal y como está ordenada la estructura, lo hace todo bien para el primer servicio, que se llama test, pero en las siguientes pasadas lo hace para alive y memory, y me dan errores indicando que están duplicados. Al final imprimo un Dumper de @duplicateArray y me dice que sólo contiene 'test'... entonces, ¿por qué me encuentra los otros servicios? Y si es fallo del grep, ¿por qué me funciona bien la primera vez?

Tampoco me funciona bien la regex (quiero que me sirva que me pasen como parámetro alive* y que haga las llamadas para alive_gps y alive_tth, por ejemplo... pero esa es otra historia), por lo que no sé si el problema es que $_ no me está devolviendo lo que yo creo que me está devolviendo; sin embargo en cada loop cuando hace la llamada lanzo este mensaje para indicarlo:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. print " Analyzing service $_ in url $completeURL\n";
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Y, según el mensaje, $_ sí tiene la clave que yo quiero.

En fin, que seguro que es una chorrada muy grande, pero yo soy tan novato como grande será dicha chorrada :)
sergiarcano
Perlero nuevo
Perlero nuevo
 
Mensajes: 19
Registrado: 2012-11-28 10:18 @471

Publicidad

Re: Elementos duplicados en un XML

Notapor explorer » 2012-11-28 18:36 @816

Bienvenido a los foros de Perl en Español, sergiarcano.

sergiarcano escribiste:El xml se carga en una estructura tipo hash (la cual reconozco que no soy capaz de "dibujar" en mi cabeza para entenderla bien)
Hazle un Dump, y listo :)

sergiarcano escribiste:He tratado de aplicar lo que previamente había probado en un script que he hecho aparte a modo de prueba:
¿Por qué has puesto un chomp()?

sergiarcano escribiste:Tampoco me funciona bien la regex (quiero que me sirva que me pasen como parámetro alive* y que haga las llamadas para alive_gps y alive_tth, por ejemplo...
En ese caso, el patrón a buscar no es 'alive*', sino 'alive\w+' o 'alive.+'. Los comodines en los patrones de expresión regular funcionan de forma diferente a los comodines de la shell.

sergiarcano escribiste:En fin, que seguro que es una chorrada muy grande, pero yo soy tan novato como grande será dicha chorrada :)
Pues el caso que el grep() sí que puede estar mal... Tienes puesto grep ( $_, @duplicateArray ). grep() devuelve los elementos de @duplicateArray para los cuales la primera expresión es verdadera. ¿Y qué es lo que tienes en la primera expresión? Pues el nombre de una clave (una cadena de caracteres). Así que... a menos que esa cadena de caracteres sea la cadena vacía, el grep() siempre devuelve verdadero, por lo que siempre te rechazará todas las claves almacenadas en @duplicateArray, a partir de la segunda clave que analices.

Esta es una solución parecida a lo que quieres hacer:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use feature 'say';
  3.  
  4. ## claves de pruebas
  5. my @claves = qw( test alive test alive test memory memory memory alive );
  6.  
  7. ## aquí almacenaremos las claves únicas
  8. my @no_repetidas;
  9.  
  10. ## Proceso...
  11. for my $clave (@claves) {
  12.     if (grep { $_ eq $clave } @no_repetidas) {
  13.         say "Clave $clave repetida";
  14.     }
  15.     else {
  16.         push @no_repetidas, $clave;
  17.     }
  18. }
  19.  
  20. say "Claves únicas: @no_repetidas";
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

El grep() analiza todos los valores de @no_repetidos. Para cada uno de ellos, los mete en $_ y mira a ver si coincide con la $clave que estamos mirando (usa el operador de igualdad, entre el valor de $_ y el valor de la $clave. Si son iguales, es que hemos encontrado una clave anterior ya vista. Si no, la "metemos" (push) en las @no_repetidas.

Pero... en Perl hay una estructura de datos que le viene al pelo en el tema de "recordar cosas ya vistas": el hash:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use feature 'say';
  3.  
  4. my @claves = qw( test alive test alive test memory memory memory alive );
  5.  
  6. my %no_repetidas;
  7.  
  8. for my $clave (@claves) {
  9.     if ($no_repetidas{$clave}++) {
  10.         say "Clave $clave repetida";
  11.     }
  12. }
  13.  
  14. say "Claves únicas: ", join " ", keys %no_repetidas;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Funciona de la siguiente manera: en el if() obtenemos primero el valor de $no_repetidas{$clave}, y luego, lo incrementamos. Eso quiere decir que en la primera vuelta de una $clave, el valor devuelto es 0, por lo que no sale el mensaje de que está repetida, y se incrementa a 1. En las sucesivas vueltas en las que aparezca la misma $clave, obtendremos un valor positivo, por lo que se activa el if() y sale el mensaje. Y se sigue incrementando (de hecho, el hash va contando cuántas veces aparece cada $clave), aunque eso no nos importa para este problema. Solo nos interesa las claves de %no_repetidas, que contendrá las claves no repetidas (de ahí su nombre ;) ).
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Elementos duplicados en un XML

Notapor sergiarcano » 2012-11-29 05:08 @255

explorer escribiste:Bienvenido a los foros de Perl en Español, sergiarcano.

Muchas gracias :)

explorer escribiste:
sergiarcano escribiste:El xml se carga en una estructura tipo hash (la cual reconozco que no soy capaz de "dibujar" en mi cabeza para entenderla bien)
Hazle un Dump, y listo :)

Sí, sí... si ahí lo veo... pero cuando empiezo a ver %xxx, $xxx, $xxx{yyy}, $xxx->{yyy}, \%xxx, keys(%{$xxx}), ref($xxx->{yyy}), xxx->{yyy}[2]->{rrr}, @{xxx->{yyy}}... ufff, me pierdo completamente, ya no sé lo que es cada cosa y qué demonios me va a devolver (eso se aplica también a $_ y @_). De todos modos digamos que llevo tan sólo una semana con Perl, así que... poco a poco :).

explorer escribiste:
sergiarcano escribiste:He tratado de aplicar lo que previamente había probado en un script que he hecho aparte a modo de prueba:
¿Por qué has puesto un chomp()?

Básicamente porque cuando uno no entiende por qué no funciona algo, empieza a hacer pruebas sin sentido... Pero vamos, funciona exactamente igual con él que sin él, así que ya está borrado.

explorer escribiste:
sergiarcano escribiste:Tampoco me funciona bien la regex (quiero que me sirva que me pasen como parámetro alive* y que haga las llamadas para alive_gps y alive_tth, por ejemplo...
En ese caso, el patrón a buscar no es 'alive*', sino 'alive\w+' o 'alive.+'. Los comodines en los patrones de expresión regular funcionan de forma diferente a los comodines de la shell.

Cierto, pero viendo ejemplos había entendido un matiz ligéramente distinto. Ya está cambiado y funcionando, aunque en realidad también me realiza la llamada de "memory" si le paso como parámetro "memo"... y sólo debería valer para "memory*", pero ya lo afinaré mejor.

explorer escribiste:
sergiarcano escribiste:En fin, que seguro que es una chorrada muy grande, pero yo soy tan novato como grande será dicha chorrada :)
Pues el caso que el grep() sí que puede estar mal... Tienes puesto grep ( $_, @duplicateArray ). grep() devuelve los elementos de @duplicateArray para los cuales la primera expresión es verdadera. ¿Y qué es lo que tienes en la primera expresión? Pues el nombre de una clave (una cadena de caracteres). Así que... a menos que esa cadena de caracteres sea la cadena vacía, el grep() siempre devuelve verdadero, por lo que siempre te rechazará todas las claves almacenadas en @duplicateArray, a partir de la segunda clave que analices.
Vale, había entendido que esa estructura funcionaba buscando el primer valor en el segundo ($_ en @duplicateArray) y devolviendo verdadero si lo encontraba (vamos, parecido a como funciona en la shell). Eso me pasa por mirar más los ejemplos y creer entenderlos, que la documentación de la propia función :)

Te agradezco mucho los ejemplos de código que me has puesto, pero no los puedo aplicar directamente porque se supone que, a priori, no conozco los nombres de las claves para meterlos en un array si no que tengo que usar una función que me han dado que me devuelve lo que tengo en el xml en una estructura hash a partir de la cual obtengo un array con una estructura como esto:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. $VAR1 = {
  2.           'service' => {
  3.                        'memory' => {
  4.                                    'xxx' => 'yyy',
  5.                                    'rrr' => {
  6.                                                 'ccc' => {
  7.                                                             'ttt' => 'ddd',
  8.                                                             'aaa' => 'sss'
  9.                                                           }
  10.                                               },
  11.                                    'qqq' => {
  12.                                                 'www' => 'yy',
  13.                                                 'eee' => 'u'
  14.                                               }
  15.                                  },
  16.                        'test' => {
  17.                                  'xxx' => 'ppp',
  18.                                  'rrr' => {
  19.                                  .
  20.                                  .
  21.                                  .
  22.                                                  }
  23.                                     }
  24.  
  25.                      }
  26.         };
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Y de ahí tengo que obtener los nombres de los servicios. Como, por lo que me dijo la persona de aquí que lleva este tema, directamente no puedo "leerlos", necesito recorrerlo con los dos foreach anidados para @xmlArray y keys(%{$_}) y entonces obtengo el nombre de los servicios en $_... y lo que he entendido es que al usar el grep, cambiará el valor de $_, ¿no?

De todos modos (perdón por el rollo), lo más gracioso es que ¡da igual! Resulta que a partir de lo que me mandaste fui haciendo pruebas para "apañarlo" a mi script y acabé descubriendo que el módulo que me han dado para usar y que inserta los valores en la estructura hash a partir del xml ¡¡descarta los duplicados!! Vamos, que usando lo que me han dado no puedo hacerlo. Si tengo que usar lo que me han dado, tendría que, en otro punto del script, leer el xml una segunda vez de otra forma para ver si hay duplicados o no...
sergiarcano
Perlero nuevo
Perlero nuevo
 
Mensajes: 19
Registrado: 2012-11-28 10:18 @471

Re: Elementos duplicados en un XML

Notapor explorer » 2012-11-29 07:11 @341

sergiarcano escribiste:Te agradezco mucho los ejemplos de código que me has puesto, pero no los puedo aplicar directamente porque se supone que, a priori, no conozco los nombres de las claves para meterlos en un array
Eso da igual. Si te fijas en el código, el array @claves solo es un ejemplo. Incluso puedes meter más claves inventadas. Lo importante es el bucle que encuentra las no repetidas.

sergiarcano escribiste:necesito recorrerlo con los dos foreach anidados para @xmlArray y keys(%{$_}) y entonces obtengo el nombre de los servicios en $_... y lo que he entendido es que al usar el grep, cambiará el valor de $_, ¿no?
Cuidado con la variable "por defecto" $_... Es la variable que almacena los valores y resultados de algunas funciones, si no se indica ninguna otra variable. Lo que hay que tener cuidado es que, si en un bucle haces uso de $_ para guardar el valor de cada elemento que recorre el bucle, no podemos usar $_ para almacenar otro valor (salvo si ese valor va a sobreescribir el elemento del bucle).

En estas líneas que tienes:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. foreach (@xmlArray) {
  2.     foreach ( keys( %{$_} ) ) {
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
estas usando $_ a dos niveles distintos, lo cual es un lío tremendo. Entonces, muchas veces, para ahorrarnos problemas, es mucho mejor poner variables normales en los bucles:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. foreach my $item_array (@xmlArray) {
  2.     foreach my $clave ( keys( %{$item_array} ) ) {
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Además, queda más claro.

sergiarcano escribiste:De todos modos (perdón por el rollo), lo más gracioso es que ¡da igual! Resulta que a partir de lo que me mandaste fui haciendo pruebas para "apañarlo" a mi script y acabé descubriendo que el módulo que me han dado para usar y que inserta los valores en la estructura hash a partir del xml ¡¡descarta los duplicados!!
Claro... porque es un hash... los hash solo guardan un valor por cada clave... y cada clave es única.

sergiarcano escribiste:Vamos, que usando lo que me han dado no puedo hacerlo. Si tengo que usar lo que me han dado, tendría que, en otro punto del script, leer el xml una segunda vez de otra forma para ver si hay duplicados o no...
¿Podrías poner un ejemplo de estructura a analizar, pero con claves repetidas?
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Elementos duplicados en un XML

Notapor sergiarcano » 2012-11-29 08:40 @403

Cambiado lo de las variables :)

explorer escribiste:
sergiarcano escribiste:De todos modos (perdón por el rollo), lo más gracioso es que ¡da igual! Resulta que a partir de lo que me mandaste fui haciendo pruebas para "apañarlo" a mi script y acabé descubriendo que el módulo que me han dado para usar y que inserta los valores en la estructura hash a partir del xml ¡¡descarta los duplicados!!
Claro... porque es un hash... los hash solo guardan un valor por cada clave... y cada clave es única.

Qué bien... entonces no sé porqué me pide ahora eso. Verás como en cuanto se lo comente decide volver a cambiar la estructura del xml y tengo que modificar de nuevo parte del script...

explorer escribiste:¿Podrías poner un ejemplo de estructura a analizar, pero con claves repetidas?

Sería algo así (espero que se entienda bien con las sustituciones):

Sintáxis: [ Descargar ] [ Ocultar ]
Using xml Syntax Highlighting
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <myXML>
  3. <service>
  4.  <name>alive_gps</name>
  5.  <qqq>1111</qqq>
  6.  <www>
  7.        <eee>
  8.         <rrr>2222</rrr>
  9.         <ttt>3333</ttt>
  10.       </eee>
  11.  </www>
  12.  <yyy uuu="1234" iii="12" />
  13. </service>
  14.  
  15. <service>
  16.  <name>test</name>
  17.  <qqq>8888</qqq>
  18.  <www>
  19.       <eee>
  20.         <rrr>5555</rrr>
  21.       </eee>
  22.  </www>
  23. </service>
  24.  
  25. <service>
  26.  <name>memory</name>
  27.  <qqq>8888</qqq>
  28.  <www>
  29.        <eee>
  30.         <rrr>2222</rrr>
  31.         <ttt>3333</ttt>
  32.       </eee>
  33.  </www>
  34.  <yyy uuu="1234" iii="12" />
  35. </service>
  36.  
  37. <service>
  38.  <name>test</name>
  39.  <qqq>1111</qqq>
  40.  <www>
  41.       <eee>
  42.         <rrr>7777</rrr>
  43.       </eee>
  44.  </www>
  45. </service>
  46.  
  47. </myXML>
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Editado: Para quitar un par de datos "sensibles"
Última edición por sergiarcano el 2012-11-30 02:56 @164, editado 1 vez en total
sergiarcano
Perlero nuevo
Perlero nuevo
 
Mensajes: 19
Registrado: 2012-11-28 10:18 @471

Re: Elementos duplicados en un XML

Notapor explorer » 2012-11-29 19:15 @844

Bueno, el XML es muy sencillo... se puede resolver en muy pocas líneas:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use v5.14;
  3. use XML::Simple;
  4.  
  5. my $xml = XMLin('code_33144.xml', ForceArray => [ 'service' ], KeyAttr => []);
  6.  
  7. #use Data::Dumper::Simple;
  8. #say Dumper $xml;
  9.  
  10. my %services_uniques;
  11.  
  12. for my $service (@{ $xml->{service} }) {
  13.     my $name = $service->{name};
  14.  
  15.     if ($services_uniques{$name}++) {
  16.         say "Servicio $name repetido";
  17.     }
  18. }
  19.  
  20. say 'Servicios únicos: ', join ' ', keys %services_uniques;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

El módulo XML::Simple, en una línea, nos lee el xml y nos lo convierte en esta estructura:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
$xml = {
         'service' => [
                      {
                        'www' => {
                                 'eee' => {
                                          'rrr' => '2222',
                                          'ttt' => '3333'
                                        }
                               },
                        'name' => 'alive_gps',
                        'yyy' => {
                                 'uuu' => '1234',
                                 'iii' => '12'
                               },
                        'qqq' => '1111'
                      },
                      {
                        'www' => {
                                 'eee' => {
                                          'rrr' => '5555'
                                        }
                               },
                        'name' => 'test',
                        'qqq' => 'index_distrib.html'
                      },
                      {
                        'www' => {
                                 'eee' => {
                                          'rrr' => '2222',
                                          'ttt' => '3333'
                                        }
                               },
                        'name' => 'memory',
                        'yyy' => {
                                 'uuu' => '1234',
                                 'iii' => '12'
                               },
                        'qqq' => 'index_distrib.html'
                      },
                      {
                        'www' => {
                                 'eee' => {
                                          'rrr' => '7777'
                                        }
                               },
                        'name' => 'test',
                        'qqq' => '1111'
                      }
                    ]
       };
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

Ya solo queda recorrerlo, y con la ayuda de un hash, podemos saber qué servicios están repetidos:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
Servicio test repetido
Servicios únicos: memory test alive_gps
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

Naturalmente... aquí no se contempla que 'alive_gps' sea igual a 'alive'. Pero solo te muestro que acceder a un XML es algo sencillo. Y muy protegido contra los futuros cambios en la estructura del xml.

No sé si te estoy ayudando, o te estoy liando más... Comentabas que partías de una estructura array/hash que representaba el xml, así que solo te queda el recorrerlo, y detectar las claves repetidas. Pero ya ves que es muy fácil (a falta de indicar qué quieres hacer con las claves que comienzan con igual nombre).
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Elementos duplicados en un XML

Notapor sergiarcano » 2012-11-30 02:40 @153

explorer escribiste:Naturalmente... aquí no se contempla que 'alive_gps' sea igual a 'alive'. Pero solo te muestro que acceder a un XML es algo sencillo. Y muy protegido contra los futuros cambios en la estructura del xml.

Precisamente para el caso que nos ocupa se supone que "alive" y "alive_gps" serían servicios distintos (aunque ambos se tendrían que ejecutar con alive*, pero no dar un error por estar duplicados).

explorer escribiste:No sé si te estoy ayudando, o te estoy liando más... Comentabas que partías de una estructura array/hash que representaba el xml, así que solo te queda el recorrerlo, y detectar las claves repetidas. Pero ya ves que es muy fácil (a falta de indicar qué quieres hacer con las claves que comienzan con igual nombre).

¡¡Claro que me estás ayudando!! :D :D . Obviamente esperaba ayuda, ideas y comentarios sobre mis fallos, pero no que alguien lo hiciese por mi :). Además, considerando que sólo he pasado como el 5% del código del script, aparte de la estructura del xml, no puedes saber por ejemplo cómo funciona el módulo que me han dado para usar y que me lee el xml. ¡¡Bastante es!!

Con las claves duplicadas no tengo que hacer nada, simplemente mirar si existe alguna y, si es así, mostrar un error y salir del programa, ya que ha debido haber un fallo al introducir la información del xml desde otro sitio (puede que, en un caso como el ejemplo, tenga que mostrar el fallo si me pasan 'test' pero ejecutarlo normal si me pasan 'memory', pero aún estoy esperando que me lo digan).

Ese módulo lo he visto un poco y es enorme, así que supongo que realizará muchos tratamientos. Lo que sí he visto es que, como yo pensaba, obviamente usa XML::Simple, pero debe hacer algún tratamiento específico, porque yo creía que era el propio XMLin() el que, al leer el xml y crear la estructura, descartaba los duplicados precisamente por lo que comentabas de que las claves en el hash son únicas. Ahora ya veo que no es el XMLin(), si no algo que hace ese módulo, y creo que tiene que ver mucho con el hecho de que XMLin() devuelve una estructura combinada de array y hash y sin embargo, la estructura que yo recibo, es solo hash. Dentro de un rato tengo una reunión con este hombre para ver precisamente este tema, pero al menos ahora ya tengo más opciones (claro... efectivamente teniendo que leer dos veces el xml, una con el módulo y otra con XMLin()... o modificando ellos el módulo).

¡¡Muchísimas gracias por la ayuda, maestro!! :D . En cuanto sepa algo nuevo lo comento (sea otra duda o la solución final al tema).
sergiarcano
Perlero nuevo
Perlero nuevo
 
Mensajes: 19
Registrado: 2012-11-28 10:18 @471

Re: Elementos duplicados en un XML

Notapor explorer » 2012-11-30 09:17 @428

sergiarcano escribiste:Lo que sí he visto es que, como yo pensaba, obviamente usa XML::Simple, pero debe hacer algún tratamiento específico, porque yo creía que era el propio XMLin() el que, al leer el xml y crear la estructura, descartaba los duplicados precisamente por lo que comentabas de que las claves en el hash son únicas. Ahora ya veo que no es el XMLin(), si no algo que hace ese módulo, y creo que tiene que ver mucho con el hecho de que XMLin() devuelve una estructura combinada de array y hash y sin embargo, la estructura que yo recibo, es solo hash.
Fíjate en las dos opciones extra que yo le pongo a XMLin() en mi código... sin ellas, XML::Simple genera la estructura pero sin claves duplicadas.

El problema es el siguiente: cuando XML::Simple está leyendo un xml, presta especial atención a todas las marcas y atributos que se llamen 'name', 'login' e 'id', y en ese caso, les da un trato especial (las descarta y su contenido va a formar parte de las claves del siguiente hash de la estructura, por lo que si hay más de un 'name' en el mismo nivel... lo perdemos al pasarlo a clave hash). Por esa razón existe la opción KeyAttr => []: para indicarle a XML::Simple que no haga eso, porque precisamente nuestro xml sí tiene una marca 'name' que no queremos que reduzca.

Te basta con coger mi programa y quitar la opción para que veas la salida tan distinta que se produce.

Más información en XML::Simple, en la sección donde se comenta la opción KeyAttr.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Elementos duplicados en un XML

Notapor sergiarcano » 2012-11-30 10:31 @480

explorer escribiste:Te basta con coger mi programa y quitar la opción para que veas la salida tan distinta que se produce.


Visto. Cierto, era la estructura que tenía antes y que no me valía.

Tras hablar con esta persona y ver el problema me comentó que no usase el módulo que me había dado (visto lo visto, es necesario modificarlo para que tenga en cuenta esa opción) y usase directamente XML::Simple. La solución final fue hacer dos pasadas al array: una para lo de los duplicados y otra para las llamadas si el fichero está bien.

Problema solucionado. Muchísimas gracias por la ayuda :).

(Iba a cerrar el hilo pero creo que yo no puedo hacerlo; si es así no veo la opción)
sergiarcano
Perlero nuevo
Perlero nuevo
 
Mensajes: 19
Registrado: 2012-11-28 10:18 @471


Volver a Básico

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 34 invitados

cron