• Publicidad

Sustituir partes XML

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

Sustituir partes XML

Notapor vicca » 2012-10-04 15:36 @692

¡Hola!

Quiero sustituir una parte de un XML.

Para ello había pensado en utilizar expresiones regulares y el operador s///.

El problema es que no soy capaz de seleccionar la parte que deseo del texto.

Os muestro un fragmento:

Sintáxis: [ Descargar ] [ Ocultar ]
Using xml Syntax Highlighting
  1.   <vm name="h3" type="libvirt" subtype="kvm" os="linux">
  2.     <filesystem type="cow">/usr/share/vnx/filesystems/rootfs_ubuntu</filesystem>
  3.    <mem>128M</mem>
  4.    <if id="1" net="Net2">
  5.       <ipv4>10.0.2.2/24</ipv4>
  6.     </if>
  7.     <route type="ipv4" gw="10.0.2.1">default</route>
  8.     <filetree seq="start-www" root="/var/www">conf/tutorial_ubuntu/h3</filetree>
  9.     <exec seq="start-www" type="verbatim" ostype="system">chmod 644 /var/www/*</exec>
  10.   </vm>
  11.  
  12.   <vm name="h4" type="libvirt" subtype="kvm" os="linux">
  13.     <filesystem type="cow">/usr/share/vnx/filesystems/rootfs_ubuntu</filesystem>
  14.     <mem>128M</mem>
  15.     <if id="1" net="Net2">
  16.       <ipv4>10.0.2.3/24</ipv4>
  17.     </if>
  18.     <route type="ipv4" gw="10.0.2.1">default</route>    
  19.     <filetree seq="start-www" root="/var/www">conf/tutorial_ubuntu/h4</filetree>
  20.     <exec seq="start-www" type="verbatim" ostype="system">chmod 644 /var/www/*</exec>
  21.   </vm>
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Querría seleccionar sólo el nodo vm cuyo atributo name es h3 y para ello he escrito la siguiente expresión regular:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
/(<vm name="h3[\W*\w*\n*]+vm>)/
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


El problema es que me selecciona todo el fragmento que os muestro, dado que tanto el nodo que quiero como todo ese código cumplen la condición de la expresión regular.

¿Cómo puedo seleccionarla?

¿Se os ocurre una forma mejor de hacerlo que con expresiones regulares?

Muchas gracias.
vicca
Perlero nuevo
Perlero nuevo
 
Mensajes: 17
Registrado: 2012-04-16 03:44 @197

Publicidad

Re: Sustituir partes XML

Notapor explorer » 2012-10-04 15:59 @707

No necesitas expresiones regulares para buscar por cadenas fijas. Puedes usar index() para encontrar la posición:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use v5.12;
  3.  
  4. my $xml = do { local $/; open F, 'code_32563.xml'; <F> };
  5.  
  6. # Buscamos el inicio de <vm name="h3"
  7. my $inicio = index($xml, '<vm name="h3"');
  8.  
  9. die "ERROR: no encontrado inicio." if $inicio == -1;
  10.  
  11. # Buscamos el final
  12. my $final  = index($xml, '</vm>', $inicio);
  13.  
  14. die "ERROR: no encontrado final." if $final == -1;
  15.  
  16. $final += 5;  # sumamos el tamaño de "</vm>"
  17.  
  18. say "Encontrado en [$inicio, $final]";
  19.  
  20. say substr($xml, $inicio, $final-$inicio);
  21.  
  22. # Sustitución
  23. substr($xml, $inicio, $final-$inicio) = "Hola, pajarota";
  24.  
  25. say "[$xml]";
  26.  
  27. __END__
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4

Ahora, también lo puedes hacer con una expresión regular:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use v5.12;
  3.  
  4. my $xml = do { local $/; open F, 'code_32563.xml'; <F> };
  5.  
  6. $xml =~ s{<vm name="h3" .+?</vm>}{Hola, pajarota}s;
  7.  
  8. say "[$xml]";
  9.  
  10. __END__
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

La clave es usar la opción '/s', para que el comodín '.+' encuentre también los caracteres de fin de línea. Y el modificador '?' hace que la búsqueda se pare en el primer encuentro de '</vm>'.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Sustituir partes XML

Notapor vicca » 2012-10-08 13:10 @590

¡Muchas gracias!
Al final me he decidido por la "versión" que utiliza la opción index().

Una última pregunta sobre el tema: ¿cómo guardo los cambios en el mismo archivo? ¿Y en otro diferente?

Como verás, el tema de lectura y escritura de ficheros no lo domino mucho... :oops:

¡Gracias de nuevo!
vicca
Perlero nuevo
Perlero nuevo
 
Mensajes: 17
Registrado: 2012-04-16 03:44 @197

Re: Sustituir partes XML

Notapor explorer » 2012-10-08 16:51 @743

De la misma manera que has usado open() para leer el archivo, puedes usar otro open() para escribirlo.

La diferencia está en que en el primero usas '<' para indicar lectura, mientras que en el segundo se debe usar '>'.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Sustituir partes XML

Notapor vicca » 2012-10-09 05:01 @250

Siento no entenderlo pero, ¿podrías explicármelo un poquito más?

Es que además no entiendo muy bien la sentencia con la que lo abrimos:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. my $xml = do { local $/; open F, 'code_32563.xml'; <F> };
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


¿Qué hacemos ahí? ¿Qué es lo que tengo que hacer para escribir?

Gracias de nuevo y siento molestar tanto.
vicca
Perlero nuevo
Perlero nuevo
 
Mensajes: 17
Registrado: 2012-04-16 03:44 @197

Re: Sustituir partes XML

Notapor explorer » 2012-10-09 16:24 @725

La línea
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
    my $xml = do { local $/; open F, 'code_32563.xml'; <F> };
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

está un poco compactada.

Lo que hace es
  • ejecutamos un comando do{}, que agrupa una serie de acciones, y devuelve un resultado, a la variable $xml
  • dentro de do{}, lo primero que hacemos es crear una copia local de la variable especial $/, lo que, de forma efectiva, lo que conseguimos es que declaramos que la lectura de archivos será en modo "absorbedor", no línea a línea, sino todo el archivo será leído de golpe, en la primera lectura
  • luego sigue un open() normal y corriente. Abrimos el archivo indicado. Como no decimos cómo, por defecto lo abrirá en modo lectura
  • y finalmente, viene la propia lectura del archivo. Como se ha dicho antes, con esta lectura se lee todo el archivo. Y no se asigna a ninguna variable escalar, sino que sale como resultado de la ejecución del do{} (por ser la última instrucción)
  • además, por terminar el do{}, el archivo abierto es automáticamente cerrado (hace un close(F))

Ya te avisé que es una línea con mucho intríngulis, dentro.

De forma más casera:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. my $FILE;
  2.  
  3. # Leer un archivo y leer sus líneas
  4. open    $FILE, '<', 'archivo_a_leer';
  5. my @lineas = <$FILE>;
  6. close   $FILE;
  7.  
  8. # Escribir un archivo
  9. open  $FILE, '>', 'archivo_a_escribir';
  10. print $FILE @lineas;
  11. close $FILE;
  12.  
  13. # Leer archivo a una variable escalar
  14. my $texto;
  15. {
  16.     undef $/;
  17.     open      $FILE, '<', 'archivo_a_leer';
  18.     $texto = <$FILE>;
  19.     close     $FILE;
  20. }
  21.  
  22. # Escribir archivo desde una variable escalar
  23. open  $FILE, '>', 'archivo_a_escribir';
  24. print $FILE $texto;
  25. close $FILE;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Tienes mucha más información, en tu ordenador, con el comando perldoc -f open, o en la web (traducido en perlfunc). También en perlopentut tienes un tutorial. Y a lo largo de estos foros tienes centenares de ejemplos.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Sustituir partes XML

Notapor vicca » 2012-10-10 05:38 @276

Muchísimas gracias por la explicación.

Me ha sido muy útil para entenderlo todo :D
vicca
Perlero nuevo
Perlero nuevo
 
Mensajes: 17
Registrado: 2012-04-16 03:44 @197


Volver a Básico

¿Quién está conectado?

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

cron