Página 1 de 1

XML::DOM

NotaPublicado: 2008-01-14 19:20 @847
por ivan23
Quería procesar ficheros de este tipo:

Sintáxis: [ Descargar ] [ Ocultar ]
Using xml Syntax Highlighting
<?xml version="1.0" standalone="yes"?>
<Mibs>
        <UBR100000>
                <SNRTotal>a</SNRTotal>
                <SNR>b</SNR>
                <CW_UNER>c</CW_UNER>
                <CW_CORR>d</CW_CORR>
                <CW_UNCORR>e</CW_UNCORR>
                <FREQ>f</FREQ>
                <OCUPACION>g</OCUPACION>
                <MODCM>h</MODCM>
                <MOD>i</MOD>
        </UBR100000>
        <UBR7200>
                <SNRTotal>a</SNRTotal>
                <SNR>b</SNR>
                <CW_UNER>c</CW_UNER>
                <CW_CORR>d</CW_CORR>
                <CW_UNCORR>e</CW_UNCORR>
                <FREQ>f</FREQ>
                <OCUPACION>g</OCUPACION>
                <MODCM>h</MODCM>
                <MOD>i</MOD>
        </UBR7200>
</Mibs>
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


por lo que instalé el módulo del CPAN de XML::DOM pero no me crea bien el árbol DOM. Me reconoce solo un hijo o cosas así. ¿Podría alguien si le pasa algo parecido o cómo solucionar este problema u otra forma de hacerlo. Muchísimas gracias.

NotaPublicado: 2008-01-15 09:59 @457
por ivan23
Perdón, ¿Cómo tendría que hacer para a partir de UBR7200, obtener todos los valores de sus nodos pertenecientes, es decir, el valor de SNRTotal, SNR ...?

NotaPublicado: 2008-01-15 18:46 @824
por explorer
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl -l
use XML::DOM;

my $parser = XML::DOM::Parser->new();
my $doc = $parser->parsefile ("kk.xml");
my $nodos = $doc->getElementsByTagName("UBR7200");

$nodo = $nodos->item(0);

#print $nodo->getNodeType;
#print $nodo->getNodeName;

@subnodos = $nodo->getChildNodes; # Nodos dentro del nodo raíz

foreach my $subnodo ( @subnodos ) {

#    print $subnodo->getNodeTypeName;

    $tipo = $subnodo->getNodeTypeName;

    if ( $tipo eq 'ELEMENT_NODE'  ) {   # Si es un nodo
        print $subnodo->getNodeName;            # Su nombre

        @subsubnodos = $subnodo->getChildNodes; # Su contenido

        foreach my $s ( @subsubnodos ) {
            print "  ", $s->getNodeValue;
        }
    }
}
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4
Sale:
Código: Seleccionar todo
SNRTotal
  a
SNR
  b
CW_UNER
  c
CW_CORR
  d
CW_UNCORR
  e
FREQ
  f
OCUPACION
  g
MODCM
  h
MOD
  i
Yo estoy más acostumbrado a XML::Simple. Quizás es que aún no le he cogido el punto a este módulo. Y seguro que se puede hacer de una forma mejor.

NotaPublicado: 2008-01-15 20:19 @888
por Jenda
A mi no me gustan los módulos que producen una mezcla grande de objetos. Me gusta más obtener un sencillo estructura de datos. Algo parecido a que produce XML::Simple, pero con mejor habilidad de controlar la estructura, olvidar inmediatamente lo que no necesito o procesar un parte del fichero cuando acaba de estar leído. No producir la estructura completa cuando en cada paso solo necesito una parte pequeña.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
use strict;
use XML::Rules;

my $parser = XML::Rules->new(
        rules => [
                _default => 'content',
                qr/^UBR\d+$/ => 'no content',
                Mibs => 'pass no content',
        ]
);

my $data = $parser->parse(\*DATA);

#use Data::Dumper;
#print Dumper($data);

foreach my $ubr (keys %$data) {
  print "$ubr: SNR=$data->{$ubr}{SNR} / SNRTotal=$data->{$ubr}{SNRTotal}\n";
}
 
__DATA__
<?xml version="1.0" standalone="yes"?>
<Mibs>
        <UBR100000>
                <SNRTotal>a</SNRTotal>
                <SNR>b</SNR>
                <CW_UNER>c</CW_UNER>
                <CW_CORR>d</CW_CORR>
                <CW_UNCORR>e</CW_UNCORR>
                <FREQ>f</FREQ>
                <OCUPACION>g</OCUPACION>
                <MODCM>h</MODCM>
                <MOD>i</MOD>
        </UBR100000>
        <UBR7200>
                <SNRTotal>a</SNRTotal>
                <SNR>b</SNR>
                <CW_UNER>c</CW_UNER>
                <CW_CORR>d</CW_CORR>
                <CW_UNCORR>e</CW_UNCORR>
                <FREQ>f</FREQ>
                <OCUPACION>g</OCUPACION>
                <MODCM>h</MODCM>
                <MOD>i</MOD>
        </UBR7200>
</Mibs>
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

NotaPublicado: 2008-01-15 21:29 @937
por explorer
Jenda te ha dado la solución para XML::Rules. Yo te doy la de XML::Simple. El elegir el uno o el otro puede ser personal... o como dice Jenda, porque no es necesario o no es posible tener todo el esquema en memoria.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl -l
use XML::Simple;

my $ref = XMLin('kk.xml');

foreach my $nodo ( keys %{$ref->{UBR7200}} ) {
    print "$nodo : $ref->{UBR7200}->{$nodo}";
}
 
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

P.D. Parece sencillo, pero el uso de XML::Simple casi siempre lleva acompañado el uso de Data::Dumper para ver la estructura que hemos leído. No deja de ser un poco rollo. Y la escritura se puede complicar mucho más (solo hay que ver algunos ejemplos en este foro). La solución de Jenda ahorra esos problemas.

NotaPublicado: 2008-01-20 07:39 @360
por ivan23
Muchísimas gracias por vuestras respuestas, me han sido de gran ayuda.

Me surgió otra pregunta, ¿podría procesar el XML si en vez de estar en un fichero lo tuviera almacenado en una variable?

Porque hasta ahora, lo que hago es almacenar lo de la variable en un fichero, pero sería más cómodo y eficiente si pudiera procesar directamente de la variable.

De nuevo, muchísimas gracias.

NotaPublicado: 2008-01-20 13:20 @597
por Jenda
Creo que todos los módulos para procesar XML aceptan el XML en una variable. Prueba a pasar el XML en lugar del nombre del fichero y vas a ver. Si no lo funciona, lee la documentación del módulo.

Por ejemplo XML::Simple::XMLin() acepta el nombre de un fichero, la variable que contiene el XML, un objeto IO::Handle o undef (en este caso va a buscar por un fichero con el mismo nombre como el script, pero la extension .xml). XML::Rules->parse() acepta la variable con el XML o el object IO::Handle compatible y hay otra función ->parsefile() que acepta el nombre de fichero.

Jenda