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:
Using perl Syntax Highlighting
#!/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
);
}Coloreado en 0.003 segundos, usando
GeSHi 1.0.8.4
el resultado es
Using xml Syntax Highlighting
<?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>Coloreado en 0.001 segundos, usando
GeSHi 1.0.8.4
mientras que si cambiamos la línea del XMLout() a
Using perl Syntax Highlighting
print XMLout
($info, RootName
=> 'owner', XMLDecl
=> 1
, NoAttr
=> 1
);Coloreado en 0.001 segundos, usando
GeSHi 1.0.8.4
entonces la salida es:
Using xml Syntax Highlighting
<?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>Coloreado en 0.002 segundos, usando
GeSHi 1.0.8.4
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.