2008-08-26 15 views
11

A veces necesito extraer rápidamente algunos datos arbitrarios de archivos XML para ponerlos en un formato CSV. ¿Cuáles son sus mejores prácticas para hacer esto en la terminal de Unix? Me encantaría algunos ejemplos de código, así que, por ejemplo, ¿cómo puedo resolver el siguiente problema?Analizando XML usando el terminal de Unix

Ejemplo de entrada XML:

<root> 
<myel name="Foo" /> 
<myel name="Bar" /> 
</root> 

Mi salida CSV deseada:

Foo, 
Bar, 

Respuesta

5

Si sólo desea los atributos nombre de cualquier elemento, que aquí hay una solución rápida pero incompleta.

(Su texto ejemplo está en el archivo de ejemplo )

grep "nombre" ejemplo | cut -d "\"" -f2,2 | xargs -I} {echo "{}",

9

utilizar un procesador XSLT de línea de comandos tal como xsltproc, saxon o xalan para analizar el XML y generar CSV. Aquí es an example, que para su caso es la hoja de estilo:

<?xml version="1.0" encoding="ISO-8859-1"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="text"/> 

    <xsl:template match="root"> 
     <xsl:apply-templates select="myel"/> 
    </xsl:template> 

    <xsl:template match="myel"> 
     <xsl:for-each select="@*"> 
      <xsl:value-of select="."/> 
      <xsl:value-of select="','"/> 
     </xsl:for-each> 
     <xsl:text>&#10;</xsl:text> 
    </xsl:template> 
</xsl:stylesheet> 
11

Peter's answer es correcto, pero da salida a una línea de alimentación de arrastre

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output method="text"/> 
    <xsl:template match="root"> 
    <xsl:for-each select="myel"> 
     <xsl:value-of select="@name"/> 
     <xsl:text>,</xsl:text> 
     <xsl:if test="not(position() = last())"> 
     <xsl:text>&#xA;</xsl:text> 
     </xsl:if> 
    </xsl:for-each> 
    </xsl:template> 
</xsl:stylesheet> 

Justo. por ejemplo, ejecutar

xsltproc stylesheet.xsl source.xml 

para generar los resultados CSV en la salida estándar.

1

He aquí un pequeño script ruby ​​que hace exactamente lo que hace su pregunta (saque un atributo llamado 'nombre' de elementos llamados 'myel'). Debe ser fácil generalizar

#!/usr/bin/ruby -w 

require 'rexml/document' 

xml = REXML::Document.new(File.open(ARGV[0].to_s)) 
xml.elements.each("//myel") { |el| puts "#{el.attributes['name']}," if el.attributes['name'] } 
6

XMLStarlet es un conjunto de herramientas de línea de comandos para consultar/editar/cheque/transformar documentos XML (para más información ver http://xmlstar.sourceforge.net/)

No hay archivos para escribir, simplemente tubo de su archivo a xmlstarlet y aplicar un filtro xpath.

cat file.xml | sel xml -t -m 'XPathExpression' -v 'elemName' 'literal' -v 'elname' -n -m expresión valor -v '' incluido literal nueva línea -n

Así que para su XPath del La expresión de xpath sería // myel/@ name que proporcionaría los dos valores de atributo.

Herramienta muy útil.

HTH

+0

XMLStarlet no parece actualizarse recientemente – Vihung

0

su archivo de prueba está en test.xml.

sed -n 's/^\s`*`&lt;myel\s`*`name="\([^"]`*`\)".`*`$/\1,/p' test.xml 

Tiene su trampas, por ejemplo, si no se le da estrictamente que cada myel está en una línea que tiene que "normalizar" el archivo XML primero (por lo que cada myel está en una línea separada)

1

Respondiendo a la pregunta original, suponiendo que el archivo XML es "test.xml" que contiene:

<root> <myel name="Foo" /> <myel name="Bar" /> </root>

cat text.xml | tr -s "\"" " " | awk '{printf "%s,\n", $3}' 
Cuestiones relacionadas