Perl en Español

  1. Home
  2. Tutoriales
  3. Foro
  4. Artículos
  5. Donativos
  6. Publicidad
 

Consulta sobre XML
Ir a página Anterior  1, 2, 3, 4  Siguiente
 
Publicar nuevo tema   Responder al tema    Foros de discusión -> Intermedio
Mensaje Dom Jun 08, 2008 12:47 am
situ
Perlero Frecuente
Perlero Frecuente
Registrado: 09 Abr 2007
Mensajes: 132
Responder citando

Consulta, ¿hay alguna forma sencilla de pasar el "-s" a argumento? Así puedo controlar mejor lo que ingresa el usuario.
Mensaje Dom Jun 08, 2008 9:35 am
explorer
Moderador
Moderador
Registrado: 24 Jul 2005
Mensajes: 4018
Ubicación: Valladolid, España
Responder citando

Sí, lo puedes sacar del código y cuando quieras, lo agregas como primer argumento del programa, desde la línea de comandos, por ejemplo.
Mensaje Dom Jun 08, 2008 7:16 pm
situ
Perlero Frecuente
Perlero Frecuente
Registrado: 09 Abr 2007
Mensajes: 132
Responder citando

Explorer,
Una consulta estoy tratando de hacer, lo siguiente, si el ARG es igual a "-name" que ejecute la función de esa opción, pero no sé cómo hacer ese if Confused no me sale.

Perl:
#!/usr/bin/perl
## Comprobacion del MODULO
BEGIN {
    eval "use XML::Simple";
    if ( $@ ) {
        warn  "Error al cargar el modulo: XML::Simple\n"
        . "Instalar Modulo:\n"
        . "\t\tcpan\n"
        . "\t\tcpan> install XML::Simple\n";
exit ();
 }
}

use XML::Simple;
use strict;

## Ayuda del sistema
if ( @ARGV != 1 ) {
    die "\nUse: $0 -opcion\n\n"
      . "   -name=pc                 Busqueda por nombre del host\n"
      . "   -notes=test              Busqueda por nota\n"
      . "   -ip=1.1.1.1              Busqueda por direccion ip\n"
      . "   -url=https://10.0.0.1    Busqueda por url\n\n"
      ;
}



## Variable globales para las busquedas
our $name;
our $notes;
our $ip;
our $url;
## Definicion de variables
my $info = XMLin("kk.xml", KeyAttr => 1, ForceArray => [ 'user' ]);
my $host = $name || '.+';
my $notes = $notes || '.+';
my $ip = $ip || '.+';


for my $pc ( @{$info->{technology}{pc}} ) {
next if $pc->{name} !~ /^$host$/;
next if $pc->{notes} !~ /^$notes$/;
next if $pc->{ip} !~ /^$ip$/;

        print "$pc->{name} => $pc->{url} ($pc->{ip})\n";

for my $user ( @{$pc->{user}} ) {

        print "\t$user->{name} : $user->{password}\n";



}

     }
Mensaje Lun Jun 09, 2008 1:17 am
explorer
Moderador
Moderador
Registrado: 24 Jul 2005
Mensajes: 4018
Ubicación: Valladolid, España
Responder citando

Varias cosas:

* Si colocas el '-s' en la primera línea del programa, Perl colocará el valor de los argumentos pasados por el usuario en las variables globales del mismo nombre, tal como te indiqué antes

* Después, dentro del programa, no está claro que el usuario pueda buscar por una, más de una, o todas las opciones. O si es obligatorio buscar por todas. Tal como lo tienes indicado en el if del @ARGV, todas las opciones son obligatorias. Pero yo creo que no es eso lo que quieres hacer, sino que sean todos opcionales

* En caso de ser opciones, hay que modificar un poco las condiciones, para tenerlas en cuenta solo en el caso de haber sido puestas.

Con esas modificaciones, el programa queda así:
Perl:
#!/usr/bin/perl -s
use strict;
use warnings;

##
BEGIN {
    eval "use XML::Simple";
    if ( $@ ) {
        warn  "Error al cargar el módulo: XML::Simple\n"
            . "Instalar Módulo:\n"
            . "\t\tcpan XML::Simple\n\n";
        exit();
    }
}

our $name;
our $notes;
our $ip;
our $url;

## Ayuda del sistema
if ( !@ARGV ) {
    die "Uso: $0 [-name|-notes|-ip|-url] <fichero xml>\n"
      . "\t-name=pc                 Búsqueda por nombre del host\n"
      . "\t-notes=test              Búsqueda por nota\n"
      . "\t-ip=1.1.1.1              Búsqueda por dirección ip\n"
      . "\t-url=https://10.0.0.1    Búsqueda por url\n\n"
      ;
}

my $info = XMLin($ARGV[0], KeyAttr => 1, ForceArray => [ 'user' ]);

for my $pc ( @{$info->{technology}{pc}} ) {
    next if $name  and $pc->{name}  !~ /^$name$/;
    next if $notes and $pc->{notes} !~ /^$notes$/;
    next if $ip    and $pc->{ip}    !~ /^$ip$/;
    next if $url   and $pc->{url}   !~ /^$url$/;

    print "$pc->{name} => $pc->{url} ($pc->{ip})\n";
    for my $user ( @{$pc->{user}} ) {
        print "\t$user->{name} : $user->{date}\n";
    }
}
Notas:
* Hemos quitado un 'use' que sobraba: el que estaba dentro del BEGIN es suficiente
* El if del @ARGV se modifica para que se ejecute en el caso de que no se le hayan pasado argumentos al programa. Como mínimo, hay que pasarle el nombre del fichero xml a procesar
* Dentro del bucle, modificamos los if para que solo funcionen en caso de haber sido indicadas como argumentos

Ahora ya se puede invocar el programa de varias formas:
Código:
explorer@joaquin:~/Documents/Desarrollo> ./kk.pl kk.xml
marcos => https://10.1.1.1 (10.1.1.1)
        admin : 20080101
        root : 20080101
marcos2 => https://10.2.2.2 (10.2.2.2)
        root : 20080102
explorer@joaquin:~/Documents/Desarrollo> ./kk.pl -name=marcos  kk.xml
marcos => https://10.1.1.1 (10.1.1.1)
        admin : 20080101
        root : 20080101
explorer@joaquin:~/Documents/Desarrollo> ./kk.pl -ip=10.2.2.2 kk.xml
marcos2 => https://10.2.2.2 (10.2.2.2)
        root : 20080102
explorer@joaquin:~/Documents/Desarrollo> ./kk.pl -url=https://10.2.2.2 kk.xml
marcos2 => https://10.2.2.2 (10.2.2.2)
        root : 20080102
explorer@joaquin:~/Documents/Desarrollo> ./kk.pl -notes=test kk.xml
marcos => https://10.1.1.1 (10.1.1.1)
        admin : 20080101
        root : 20080101


Se puede hacer la siguiente variación: en el caso de que el fichero xml sea siempre el mismo, entonces lo dejamos indicado en el programa, como teníamos antes:
Perl:
my $info = XMLin('kk.xml', KeyAttr => 1, ForceArray => [ 'user' ]);
Entonces tenemos que modificar el primer if:
Perl:
our $h;
if ( $h ) {
    die "Uso: $0 [-h|-name|-notes|-ip|-url] <fichero xml>\n"
      . "\t-name=pc                 Búsqueda por nombre del host\n"
      . "\t-notes=test              Búsqueda por nota\n"
      . "\t-ip=1.1.1.1              Búsqueda por dirección ip\n"
      . "\t-url=https://10.0.0.1    Búsqueda por url\n\n"
      ;
}
Así, si el usuario ejecuta el programa sin más, vuelca todo el fichero. Si indica '-h', sale la ayuda y termina.

Pero si quisiéramos que el usuario ponga al menos una opción de filtrado, deberíamos ponerlo también en el primer if:
Perl:
if ( !$name and !$notes and !$ip and !$url ) {
    die "Uso: $0 [-name|-notes|-ip|-url] <fichero xml>\n"
      . "\t-name=pc                 Búsqueda por nombre del host\n"
      . "\t-notes=test              Búsqueda por nota\n"
      . "\t-ip=1.1.1.1              Búsqueda por dirección ip\n"
      . "\t-url=https://10.0.0.1    Búsqueda por url\n\n"
      ;
}


Ultima edición por explorer el Lun Jun 09, 2008 10:57 am, editado 1 vez
Mensaje Lun Jun 09, 2008 9:46 am
situ
Perlero Frecuente
Perlero Frecuente
Registrado: 09 Abr 2007
Mensajes: 132
Responder citando

Muchísimas gracias
Mensaje Lun Jun 09, 2008 11:00 am
situ
Perlero Frecuente
Perlero Frecuente
Registrado: 09 Abr 2007
Mensajes: 132
Responder citando

Te hago una consulta. ¿Este módulo tiene para escribir en el XML?, porque mi idea es más adelante poder ingresar más datos al XML desde la consola.

EDIT:
Ahí lo encontré:
http://search.cpan.org/dist/XML-Writer/Writer.pm

Voy a ver si puedo adaptarlo Very Happy
Mensaje Lun Jun 09, 2008 12:44 pm
explorer
Moderador
Moderador
Registrado: 24 Jul 2005
Mensajes: 4018
Ubicación: Valladolid, España
Responder citando

Puedes escribirlo con la función XMLout() del mismo módulo XML::Simple.
Mensaje Lun Jun 09, 2008 1:54 pm
situ
Perlero Frecuente
Perlero Frecuente
Registrado: 09 Abr 2007
Mensajes: 132
Responder citando

Explorer,
Tenes algun ejemplo que no sea este:
http://perlenespanol.baboonsoftware.com/foro/viewtopic.php?t=1261&highlight=xml+simple
Ya que no lo logro hacer funcionar
Mensaje Lun Jun 09, 2008 2:47 pm
explorer
Moderador
Moderador
Registrado: 24 Jul 2005
Mensajes: 4018
Ubicación: Valladolid, España
Responder citando

Hay un montón de ejemplos en estos foros. Busca por las palabras XML y Simple. Activa la opción "Buscar todas las palabras". También puedes restringir la búsqueda a los mensajes escritor por mí (pon 'explorer' en la caja de autores). Puedes reducir aún más la búsqueda, agregando la palabra XMLout. Salen 6 hilos, incluido este.
Mensaje Lun Jun 09, 2008 3:51 pm
situ
Perlero Frecuente
Perlero Frecuente
Registrado: 09 Abr 2007
Mensajes: 132
Responder citando

Consulta, me quedó el siguiente script.

Perl:
#!/usr/bin/perl -s
use strict;
use warnings;

##
BEGIN {
    eval "use XML::Simple";
    if ( $@ ) {
        warn  "Error al cargar el modulo: XML::Simple\n"
            . "Instalar Modulo:\n"
            . "\t\tcpan XML::Simple\n\n";
        exit();
    }
}

our $name;
our $notes;
our $ip;
our $url;

## Ayuda del sistema
if ( !$name and !$notes and !$ip and !$url ) {
    die "Uso: $0 [-name|-notes|-ip|-url]\n"
      . "\t-name=pc                 Busqueda por nombre del host\n"
      . "\t-notes=test              Busqueda por nota\n"
      . "\t-ip=1.1.1.1              Busqueda por direccion IP\n"
      . "\t-url=https://10.0.0.1    Busqueda por url\n\n"
      ;
}

my $info = XMLin('kk.xml', KeyAttr => 1, ForceArray => [ 'user' ]);

for my $pc ( @{$info->{technology}{pc}} ) {
    next if $name  and $pc->{name}  !~ /^$name$/;
    next if $notes and $pc->{notes} !~ /^$notes$/;
    next if $ip    and $pc->{ip}    !~ /^$ip$/;
    next if $url   and $pc->{url}   !~ /^$url$/;

    print "$pc->{name} => $pc->{url} ($pc->{ip})\n";
    for my $user ( @{$pc->{user}} ) {
        print "\t$user->{name} : $user->{password}\n";
    }
}

sub crear{
my $xml = << "END_OF_XML";
<pc>
    <name>marcos3</name>
    <url>https://10.1.1.1</url>
        <ip>10.3.3.3.</ip>
    <user name="admin"><password>4444</password><date>20080333</date></user>
    <notes>culito</notes>
</pc>
END_OF_XML
open  $fh, q{>>:encoding(iso-8859-1)}, 'kk.xml';
print $fh $xml;
close $fh;
}


Ahora me gustaría hacer que cuando alguien pone:
Código:
./prueba.pl -crear

Se ejecute la función "crear".

Otro punto que no logro resolver es que al enviarle a mi XML la nueva información se pone errónea, ya que no tengo los parámetros.
XML:
</technology>
</owner>

Que fueron cerrados anteriormente.

Si alguno me puede ayudar, se lo voy agradecer mucho Very Happy
Mensaje Lun Jun 09, 2008 4:03 pm
explorer
Moderador
Moderador
Registrado: 24 Jul 2005
Mensajes: 4018
Ubicación: Valladolid, España
Responder citando

No se parece mucho ese XML al que has enseñado en mensajes anteriores...
Mensaje Lun Jun 09, 2008 4:16 pm
situ
Perlero Frecuente
Perlero Frecuente
Registrado: 09 Abr 2007
Mensajes: 132
Responder citando

Es el XMl que me arreglaste vos.
XML:
<?xml version="1.0"?>
<owner>
        <technology name="test">
                <pc>
                        <name>marcos</name>
                        <url>https://10.1.1.1</url>
                        <ip>10.1.1.1</ip>
                        <user name="admin"><password>123</password><date>20080101</date></user>
                        <user name="root"><password>123</password><date>20080101</date></user>
                        <notes>test</notes>
                </pc>
                <pc>
                        <name>marcos2</name>
                        <url>https://10.2.2.2</url>
                        <ip>10.2.2.2</ip>
                        <user name="root"><password>asd</password><date>20080102</date></user>
                        <notes>testno</notes>
                </pc>
        </technology>
</owner>


Ese uso, ahora quería hacer para agregar yo desde el script.

El script es que también me arreglaste, solamente le agregue la función de crear, que la saque de otro post.
Mensaje Lun Jun 09, 2008 6:22 pm
explorer
Moderador
Moderador
Registrado: 24 Jul 2005
Mensajes: 4018
Ubicación: Valladolid, España
Responder citando

Repito: el módulo XML::Simple es para hacer cosas sencillas. Si queremos hacer cosas más elaboradas es mejor usar otros módulos.

En el caso que nos ocupa, yo siempre he tenido que pedir ayuda al módulo Data::Dumper, para ver la forma que tiene la estructura que XMLin() me devuelve. Y luego, usar esa misma estructura. Pero no siempre se consigue una salida perfecta con XMLout().

Por ejemplo:
Perl:
#!/usr/bin/perl -s
use strict;
use warnings;

##
BEGIN {
    eval "use XML::Simple";
    if ( $@ ) {
        warn  "Error al cargar el modulo: XML::Simple\n"
            . "Instalar Modulo:\n"
            . "\t\tcpan XML::Simple\n\n";
        exit();
    }
}

our $crear;
our $name;
our $notes;
our $ip;
our $url;

## Ayuda del sistema
if ( !$name and !$notes and !$ip and !$url and !$crear ) {
    die "Uso: $0 [-name|-notes|-ip|-url]\n"
      . "\t-name=pc                 Busqueda por nombre del host\n"
      . "\t-notes=test              Busqueda por nota\n"
      . "\t-ip=1.1.1.1              Busqueda por direccion IP\n"
      . "\t-url=https://10.0.0.1    Busqueda por url\n\n"
      . "\t-crear                   Añade nuevos contenidos"
      ;
}

my $info = XMLin('kk.xml', KeyAttr => 1, ForceArray => [ 'user' ]);

if ( !$crear ) {
    for my $pc ( @{$info->{technology}{pc}} ) {
        next if $name  and $pc->{name}  !~ /^$name$/;
        next if $notes and $pc->{notes} !~ /^$notes$/;
        next if $ip    and $pc->{ip}    !~ /^$ip$/;
        next if $url   and $pc->{url}   !~ /^$url$/;

        print "$pc->{name} => $pc->{url} ($pc->{ip})\n";
        for my $user ( @{$pc->{user}} ) {
            print "\t$user->{name} : $user->{password}\n";
        }
    }
}
else {
    push @{$info->{technology}{pc}}, {
        name    => 'marcos3',
        url     => 'https://10.1.1.1',
        ip      => '10.3.3.3',
        user    => [{
                        name    => 'admin',
                        password=> 4444,
                        date    => 20080333,
                    }],
        notes   => 'culito',
    };
    #use Data::Dumper;
    #print Dumper $info;

    print XMLout($info, RootName => 'owner', XMLDecl => 1 );
}
el resultado es
XML:
<?xml version='1.0' standalone='yes'?>
<owner>
  <technology name="test">
    <pc name="marcos" ip="10.1.1.1" notes="test" url="https://10.1.1.1">
      <user name="admin" date="20080101" password="123" />
      <user name="root" date="20080101" password="123" />
    </pc>
    <pc name="marcos2" ip="10.2.2.2" notes="testno" url="https://10.2.2.2">
      <user name="root" date="20080102" password="asd" />
    </pc>
    <pc name="marcos3" ip="10.3.3.3" notes="culito" url="https://10.1.1.1">
      <user name="admin" date="20080333" password="4444" />
    </pc>
  </technology>
</owner>
mientras que si cambiamos la línea del XMLout() a
Perl:
print XMLout($info, RootName => 'owner', XMLDecl => 1, NoAttr => 1 );
entonces la salida es:
XML:
<?xml version='1.0' standalone='yes'?>
<owner>
  <technology>
    <name>test</name>
    <pc>
      <name>marcos</name>
      <ip>10.1.1.1</ip>
      <notes>test</notes>
      <url>https://10.1.1.1</url>
      <user>
        <name>admin</name>
        <date>20080101</date>
        <password>123</password>
      </user>
      <user>
        <name>root</name>
        <date>20080101</date>
        <password>123</password>
      </user>
    </pc>
    <pc>
      <name>marcos2</name>
      <ip>10.2.2.2</ip>
      <notes>testno</notes>
      <url>https://10.2.2.2</url>
      <user>
        <name>root</name>
        <date>20080102</date>
        <password>asd</password>
      </user>
    </pc>
    <pc>
      <name>marcos3</name>
      <ip>10.3.3.3</ip>
      <notes>culito</notes>
      <url>https://10.1.1.1</url>
      <user>
        <name>admin</name>
        <date>20080333</date>
        <password>4444</password>
      </user>
    </pc>
  </technology>
</owner>
Los dos xml son perfectamente válidos, pero no están formateados según como nosotros queremos. Según la documentación de XML::Simple, con un poco de esfuerzo se puede conseguir definir cómo queremos exactamente esa salida, para que coincida con la que le dimos en la entrada. Pero la experiencia dice que, en algunas ocasiones, esa salida es casi imposible de encontrar con las opciones que se le pueden pasar a XMLout(). En esos casos, lo mejor es usar otro módulo XML distinto.

En los desarrollos en los que yo he utilizado XML::Simple, siempre me he preocupado de que tanto la salida como la entrada sean muy sencillos de generar. Para esto he seguido la siguiente estrategia: He creado primero la estructura de datos. Y luego la he mandado grabar con XMLout(). El resultado es un fichero xml. Luego, averiguar la combinación que debo usar en XMLin() para obtener la misma estructura de datos.

¿Qué otras alternativas hay? Hay centenares de módulos para XML. Yo probaría XML::Smart (llevo años buscando una buena escusa para usarlo), ya que es mucho más fácil de manejar que XML::Simple.
Mensaje Lun Jun 09, 2008 11:51 pm
situ
Perlero Frecuente
Perlero Frecuente
Registrado: 09 Abr 2007
Mensajes: 132
Responder citando

Muchisimas gracias, como siempre aprendo mucho de este foro Very Happy
Mensaje Mar Jun 10, 2008 4:44 pm
situ
Perlero Frecuente
Perlero Frecuente
Registrado: 09 Abr 2007
Mensajes: 132
Responder citando

Explorer,
Una consulta ahi pude ir advanzando con el script, ahora puedo encriptar y desencriptar la password Very Happy.
Como puedo hacer para que la persona pueda ingresar mas de un usuario cuando esta creando un nuevo Host.

Perl:

#!/usr/bin/perl -s
use strict;
use warnings;
use POSIX qw(strftime);
my $hday= strftime("%Y%m%d", localtime);

##Verificacion del modulo XML::Simple
BEGIN {
    eval "use XML::Simple";
    if ( $@ ) {
        warn  "Error al cargar el modulo: XML::Simple\n"
            . "Instalar Modulo:\n"
            . "\t\tcpan XML::Simple\n\n";
        exit();
    }
}

our $crear;
our $name;
our $notes;
our $ip;
our $url;
our $descrypt;

## Ayuda del sistema
if ( !$name and !$notes and !$ip and !$url and !$crear and !$descrypt) {
    die "Uso: $0 [-name|-notes|-ip|-url|-crear|-descrypt]\n"
      . "\t-name=pc                 Busqueda por nombre del host\n"
      . "\t-notes=test              Busqueda por nota\n"
      . "\t-ip=1.1.1.1              Busqueda por direccion IP\n"
      . "\t-url=https://10.0.0.1    Busqueda por url\n"
      . "\t-crear                   Adjuntar nuevos contenidos\n"
          . "\t-descrypt                Desencriptar password\n"
      ;
}

my $info = XMLin('kk.xml', KeyAttr => 1, ForceArray => [ 'user' ]);

if ( $name and $descrypt ) {
            print "- Ingresar password de la key gpg\n";
            system("gpg --no-options $name.pw.asc");
            open my $FILE, '<', "$name.pw" or die $!;
        my @lines = <$FILE>;
            for my $pc ( @{$info->{technology}{pc}} ) {
        next if $name  and $pc->{name}  !~ /^$name$/;
        print "$pc->{name} => $pc->{url} ($pc->{ip})\n";
    for my $user ( @{$pc->{user}} ) {
        print "\t   $user->{name} : @lines\n";
        system("rm -f $name.pw");
                close $FILE;
                exit ();
        }
    }


}

if ( !$crear ) {
    for my $pc ( @{$info->{technology}{pc}} ) {
        next if $name  and $pc->{name}  !~ /^$name$/;
        next if $notes and $pc->{notes} !~ /^$notes$/;
        next if $ip    and $pc->{ip}    !~ /^$ip$/;
        next if $url   and $pc->{url}   !~ /^$url$/;
        print "$pc->{name} => $pc->{url} ($pc->{ip})\n";
        for my $user ( @{$pc->{user}} ) {
            print "\t   $user->{name} : $user->{password}\n";
        }
    }
}

else {
    print "- Ingresar nombre del Host: ";
    my $hname=<STDIN>;
    chop($hname);
    print "- Ingresar url: ";
    my $hurl=<STDIN>;
    chop($hurl);
    print "- Ingresar IP: ";
    my $hip=<STDIN>;
    chop($hip);
        print "- Ingresar notas: ";
    my $hnota=<STDIN>;
    chop($hnota);
    print "- Ingresar usuario: ";
    my $huser=<STDIN>;
    chop($huser);
## Creacion del archivo del password y la encriptacion
    open  (my $NHOST , "> $hname.pw");
    print "- Ingresar password (el password no aparece): ";
    system "stty -echo";
    my $hpass=<STDIN>;
    chop($hpass);
    print $NHOST "$hpass";
    close ($NHOST);
    system "stty echo";
        print "\n- Ingresar password de la key gpg\n";
        system("gpg -ac --no-options $hname.pw");
        system("rm -f $hname.pw");
##Termina  el archivo del password y la encriptacion   

   push @{$info->{technology}{pc}}, {
        name    => $hname,
        url     => $hurl,
        ip      => $hip,
        user    => [{
                        name    => $huser,
                        password=> "$hname.pw.asc",
                        date    => $hday,
                    }],
        notes   => $hnota,
    };
#use Data::Dumper;
#print Dumper $info;
#Escribo sobre el archivo xml la salida
open  my $SV, q{>:encoding(iso-8859-1)}, 'kk.xml';
print $SV XMLout($info, RootName => 'owner', XMLDecl => 1, NoAttr => 1 );
close ($SV)
}


Gracias.
Publicar nuevo tema   Responder al tema    Foros de discusión -> Intermedio Todas las horas son GMT - 6 Horas
Ir a página Anterior  1, 2, 3, 4  Siguiente
Página 2 de 4



Powered by phpBB © 2001, 2005 phpBB Group