Extracción de datos de un simple archivo XML

Tengo un archivo XML con los contenidos:

 programming 

Necesito una forma de extraer lo que está en las tags , programmin en este caso. Esto debe hacerse en el prompt del comando de Linux, usando grep / sed / awk.

¿De verdad tienes que usar solo esas herramientas? No están diseñados para el procesamiento de XML, y aunque es posible obtener algo que funcione bien la mayor parte del tiempo, fallará en casos extremos, como encoding, saltos de línea, etc.

Recomiendo xml_grep:

 xml_grep 'job' jobs.xml --text_only 

Lo que le da la salida:

 programming 

En ubuntu / debian, xml_grep está en el paquete xml-twig-tools.

  grep '"|cut -f1 -d"<" 

No utilice el análisis basado en líneas y expresiones regulares en XML. Es una mala idea Puede tener XML semánticamente idéntico con diferentes formatos, y el análisis basado en expresiones y líneas simplemente no lo puede hacer.

Cosas como tags unarias y ajuste de línea variable: estos fragmentos ‘dicen’ lo mismo:

         

Esperemos que esto aclare por qué es difícil hacer un analizador basado en expresiones regulares / líneas. Afortunadamente, no es necesario. Muchos lenguajes de scripting tienen al menos una, a veces más opciones de analizador.

Como ha mencionado un cartel anterior: xml_grep está disponible. Esa es en realidad una herramienta basada en la biblioteca XML::Twig perl. Sin embargo, lo que hace es usar ‘xpath expressions’ para encontrar algo, y diferencia entre la estructura del documento, los atributos y el ‘contenido’.

P.ej:

 xml_grep 'job' jobs.xml --text_only 

Sin embargo, con el fin de obtener mejores respuestas, aquí hay un par de ejemplos de ‘roll your own’ basados ​​en sus datos de origen:

Primera forma:

Use twig handlers que capturen elementos de un tipo particular y actúen sobre ellos. La ventaja de hacerlo de esta manera es que analiza el XML ‘sobre la marcha’, y le permite modificarlo en el vuelo si es necesario. Esto es particularmente útil para descartar XML ‘procesado’ cuando se trabaja con archivos grandes, utilizando purge o flush :

 #!/usr/bin/perl use strict; use warnings; use XML::Twig; XML::Twig->new( twig_handlers => { 'job' => sub { print $_ ->text } } )->parse( <> ); 

El cual usará <> para tomar entrada (ingresada, o especificada a través de la línea de comando ./myscript somefile.xml ) y procesarla – cada elemento del job , extraerá e imprimirá cualquier texto asociado. (Es posible que desee print $_ -> text,"\n" para insertar un salto de línea).

Debido a que coincide en elementos de “trabajo”, también coincidirá en elementos de trabajo nesteds:

 programming anotherjob  

Coincidirá dos veces, pero también imprimirá algo de la salida dos veces. Sin embargo, puede combinar en /job si lo prefiere. Útil: esto le permite, por ejemplo, imprimir y eliminar un elemento o copiar y pegar uno modificando la estructura XML.

Alternativamente – analizar primero, e ‘imprimir’ en función de la estructura:

 my $twig = XML::Twig->new( )->parse( <> ); print $twig -> root -> text; 

Como el job es su elemento raíz, todo lo que necesitamos hacer es imprimir el texto del mismo.

Pero podemos ser un poco más exigentes, y buscar job o /job e imprimirlo específicamente en su lugar:

 my $twig = XML::Twig->new( )->parse( <> ); print $twig -> findnodes('/job',0)->text; 

Puede usar la opción pretty_print XML::Twig para reformatear su XML también:

 XML::Twig->new( 'pretty_print' => 'indented_a' )->parse( <> ) -> print; 

Hay una variedad de opciones de formato de salida, pero para XML más simple (como el suyo) la mayoría se verá bastante similar.

solo use awk, no necesita otras herramientas externas. A continuación, funciona si las tags deseadas aparecen en multitine.

 $ cat file test programming  programming $ awk -vRS="" '{gsub(/.*/,"");print}' file programming programming 

Usando xmlstarlet:

 echo 'programming' | \ xmlstarlet sel -N var="http://www.sample.com/" -t -m "//var:job" -v '.' 

Suponiendo la misma línea, entrada de stdin:

 sed -ne '/<\/job>/ { s/<[^>]*>\(.*\)<\/job>/\1/; p }' 

notas: -n detiene la salida de todo automáticamente; -e significa que es un juego de una sola línea (aot a script) /<\/job> actúa como un grep; s elimina los atributos de opentag + y etiqueta final; ; es una nueva statement; p impresiones; {} hace que grep se aplique a ambas instrucciones, como una sola.

Usando el comando sed :

Ejemplo:

 $ cat file.xml  Tove Jani Reminder Don't forget me this weekend!  $ cat file.xml | sed -ne '//s#\s*<[^>]*>\s*##gp' Reminder 

Explicación:

cat file.xml | sed -ne '//s#\s*<[^>]*>\s*##gp'

n : suprima la impresión de todas las líneas
e – script

// – encuentra líneas que contienen un patrón especificado, por ejemplo,

siguiente es la parte de sustitución s///p que elimina todo menos el valor deseado donde / se reemplaza con # para una mejor legibilidad:

s#\s*<[^>]*>\s*##gp
\s* – incluye espacios en blanco si existen (los mismos al final)
<[^>]*> representa como causa alternativa no codiciosa de regulares <.*?> no funciona para sed
g – sustituye todo, p. ej., cerrando la etiqueta xml

Qué tal si:

 cat a.xml | grep '' -f 2 | cut -d '<' -f 1 

Un poco tarde para el espectáculo.

xmlcutty corta los nodos de XML:

 $ cat file.xml  programming designing managing teaching 

El argumento path nombra la ruta al elemento que desea cortar. En este caso, dado que no estamos interesados ​​en las tags, cambiamos el nombre de la etiqueta a \n , por lo que obtenemos una buena lista:

 $ xmlcutty -path /job -rename '\n' file.xml programming designing managing teaching 

Tenga en cuenta que el XML no era válido para comenzar (ningún elemento raíz). xmlcutty también puede funcionar con XML ligeramente roto.